Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Projet Calculateur
#37
J'ai enfin commencé l'arbre de probabilité qui va jusqu'à la sauvegarde.

Pour commencer, afin de faciliter la lecture du code, j'ai fait un gros refactoring pour introduire les données du calcul:
Code:
package com.calculateur.warhammer.calcul.mort.arbre.data;

import com.calculateur.warhammer.data.action.IContexteAction;
import com.calculateur.warhammer.data.enumeration.EGestionDe;
import com.calculateur.warhammer.data.unite.IConstituantAttaquant;
import com.calculateur.warhammer.data.unite.IConstituantDefenseur;

/**
* Encapsulation des données nécessaires pour générer l'arbre de probabilité.
* @author phili
*
*/
public interface IDataCalculProbabilite {

    /**
     *
     * @return Le contexte de l'action
     */
    IContexteAction getContexteAction();
    
    /**
     *
     * @return L'attaquant
     */
    IConstituantAttaquant getAttaquant();
    
    /**
     *
     * @return Le défenseur
     */
    IConstituantDefenseur getDefenseur();
    
    /**
     *
     * @return La Gestion du nombre d'attaque (partie aléatoire)
     */
    EGestionDe getGestionNombreAttaque();
    
    /**
     *
     * @return La Gestion des jets de dés pour la touche et la blessure.
     */
    EGestionDe getGestionJetToucheBlessure();
    
    /**
     *
     * @return La gestion des sauvegarde du défenseur.
     */
    EGestionDe getGestionSauvegardeDefenseur();
}

L'arbre est représenté par un noeud, qui permet d'avoir la probabilité (de l'évnement et au sein de l'arbre), le pool de dé restant, ainsi que les renfant, le parent, et sa description et libellé. Le noeud est donc traduisible:
Code:
package com.calculateur.warhammer.calcul.mort.arbre;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import org.apache.commons.math3.fraction.Fraction;

import com.calculateur.warhammer.base.traduction.ITraduction;
import com.calculateur.warhammer.calcul.de.EDe;
import com.calculateur.warhammer.data.enumeration.EBlessure;

/**
* Représente un noeud de l'arbre de probabilité
* @author phili
*
*/
public interface INoeudArbre extends ITraduction{

    /**
     *
     * @return La nature du noed.
     */
    ENatureNoeud getNatureNoeud();
    
    /**
     *
     * @return La probabilité que l'évènement ait lieu.
     */
    Fraction getProbabiliteNoeud();
    
    /**
     *
     * @return La probabilité conditionnelle en prenant en compte l'évènement précédent. Soit la probabilité au sein de l'arbre.
     */
    default Fraction getProbabiliteConditionnelle() {
        Optional<INoeudArbre> oPrecedent = precedent();
        Fraction proba = getProbabiliteNoeud();
        if(oPrecedent.isPresent()) {
            proba = proba.multiply(oPrecedent.get().getProbabiliteConditionnelle());
        }
        return proba;
    }
    
    /**
     *
     * @return L'évènement précédent.
     */
    Optional<INoeudArbre> precedent();
    
    /**
     *
     * @return Les enfants
     */
    List<INoeudArbre> enfants();
    
    /**
     *
     * @return Les noeuds de l'arbre.
     */
    Set<INoeudArbre> arbre();
    
    /**
     *
     * @return Le nombre de dé dans le pool à cette étape.
     */
    Integer getNombreDansPoolDe();
    
    /**
     *
     * @return Libellé du noeud
     */
    String libelle();
    
    /**
     * Description du noeud.
     * @return
     */
    String description();
    
    /**
     *
     * @return Le nombre de blessures sur ce noud accumuulé depuis me début.
     */
    Map<EBlessure, Integer> mapBlessure();
    
    /**
     *
     * @return Le nombre de blessures dont les dégâts sont déterminés aux dés
     */
    Map<EDe, Map<EBlessure, Integer>> mapBlessuresAleatoires();
}

On stocke aussi les blessures infligées.

On peut donc construire le contrat qui donne l'arbre (ici, de fait, la racine):
Code:
package com.calculateur.warhammer.calcul.mort.arbre.calcul;

import com.calculateur.warhammer.base.exception.FunctionnalExeption;
import com.calculateur.warhammer.calcul.mort.arbre.INoeudArbre;
import com.calculateur.warhammer.calcul.mort.arbre.data.IDataCalculProbabilite;

/**
* Interface pour calculer l'arbre de probabilité
* @author phili
*
*/
public interface ICalculArbre {

    /**
     * Calcul l'ensemble de l'arbre de probabilité et retourne la racine
     * @param data Les données pour le calcul
     * @return Le noeud racine
     * @throws FunctionnalExeption
     */
    INoeudArbre getRacine(IDataCalculProbabilite data)throws FunctionnalExeption;
}
Qui a l'implémentation suivante:
Code:
package com.calculateur.warhammer.calcul.mort.arbre.calcul;

import com.calculateur.warhammer.base.exception.FunctionnalExeption;
import com.calculateur.warhammer.calcul.mort.arbre.INoeudArbre;
import com.calculateur.warhammer.calcul.mort.arbre.NoeudJetTouche;
import com.calculateur.warhammer.calcul.mort.arbre.data.IDataCalculProbabilite;
import com.calculateur.warhammer.calcul.mort.parametres.IParametres;
import com.calculateur.warhammer.calcul.mort.validation.IValidationCalcul;
import com.calculateur.warhammer.calcul.mort.validation.ValidationContextAction;

public class CalculArbre implements ICalculArbre{

    private final IParametres parametres;
    
    private final IValidationCalcul validationContext;
    
    public CalculArbre(IParametres parametres) {
        this.parametres = parametres;
        validationContext = new ValidationContextAction();
    }

    @Override
    public INoeudArbre getRacine(IDataCalculProbabilite data) throws FunctionnalExeption {
        //Validation
        validationContext.valideCalcul(data);
        
        for(IValidationCalcul validationCalcul:parametres.getFactoryValidation().getValidations(data.getContexteAction().getSimule())) {
            validationCalcul.valideCalcul(data);
        }
        
        //Initialisation diverse
        parametres.getFactoryInitialisation().getInterfaceInitialisationAttaquant().initialiseAttaquant(data.getAttaquant());
        
        Integer nombreAttaque = parametres.getFactoryAttaque().getInterfaceCalculNombreAttaque(data.getGestionNombreAttaque()).getNombreAttaque(data)
                * data.getAttaquant().getNombre();
        INoeudArbre racine;
        
        if(data.getAttaquant().getRegles().isIgnoreJetTouche()) {
            racine = null;//TODO
        }else {
            racine = NoeudJetTouche.getJetToucheAsRacine(nombreAttaque, data, parametres);
        }
        return racine;
    }

}
La prochaine étape sera de faire la cas des lances-flammes.

On fait donc un TU générique:
Code:
package com.calculateur.warhammer.calcul.mort.arbre.calcul;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.Locale;
import java.util.logging.Logger;

import org.apache.commons.math3.fraction.Fraction;
import org.assertj.core.api.Assertions;

import com.calculateur.warhammer.base.exception.FunctionnalExeption;
import com.calculateur.warhammer.base.traduction.AbstractTraductionTest;
import com.calculateur.warhammer.calcul.mort.arbre.ENatureNoeud;
import com.calculateur.warhammer.calcul.mort.arbre.INoeudArbre;
import com.calculateur.warhammer.calcul.mort.arbre.data.IDataCalculProbabilite;
import com.calculateur.warhammer.calcul.mort.parametres.ParametresBuilder;

public abstract class AbstractCalculArbreTest {

    private static final Logger LOGGER = Logger.getLogger(AbstractCalculArbreTest.class.getName());
    
    private static final Fraction ENSEMBLE = new Fraction(1);
    
    private static final Locale[] LOCALES = AbstractTraductionTest.LOCALES_APPLICATION ;
    
    private final ICalculArbre calculArbre;
    
    public AbstractCalculArbreTest() {
        calculArbre = new CalculArbre(ParametresBuilder.getInstance().build());
    }
    
    protected INoeudArbre doTestStandard(IDataCalculProbabilite data,Fraction probaAttendu,Integer poolReussite) throws FunctionnalExeption{
        INoeudArbre racine = calculArbre.getRacine(data);
        Integer nombreReussite = 0;
        Fraction probaReussite = new Fraction(0);
        boolean racineFound = false;
        for(INoeudArbre noeud:racine.arbre()) {
            if(noeud == racine) {
                racineFound = true;
            }
            if(noeud.getNatureNoeud() == ENatureNoeud.REUSSITE) {
                nombreReussite += noeud.getNombreDansPoolDe();
                probaReussite = probaReussite.add(noeud.getProbabiliteConditionnelle());
            }
            validateNoeud(noeud);
        }
        assertThat(racineFound).isTrue();
        assertThat(probaReussite).isEqualTo(probaAttendu);
        assertThat(nombreReussite).isEqualTo(poolReussite);
        return racine;
    }
    
    private void validateNoeud(INoeudArbre noeud) {
        //Racince
        if(noeud.precedent().isEmpty()) {
            assertThat(noeud.getProbabiliteNoeud()).isEqualTo(ENSEMBLE);
            assertThat(noeud.getProbabiliteConditionnelle()).isEqualTo(noeud.getProbabiliteNoeud());
            valideEtapeIntermediaire(noeud);
        }else {
            Assertions.assertThat(noeud.getProbabiliteConditionnelle()).isEqualTo(noeud.getProbabiliteNoeud().multiply(noeud.precedent().get().getProbabiliteConditionnelle()));
            
            if(noeud.getNatureNoeud().isEnfant()) {
                valideEtapeIntermediaire(noeud);
            }else {
                assertThat(noeud.enfants()).isEmpty();
            }
        }
        valideTraduction(noeud);
    }
    
    private void valideTraduction(INoeudArbre noeud) {
        for(Locale locale:LOCALES) {
            Assertions.assertThat(noeud.getResourceBundle(locale)).isNotNull();
            noeud.traduireLibelles(locale);
            Assertions.assertThat(noeud.libelle()).isNotNull();
            Assertions.assertThat(noeud.description()).isNotNull();
            LOGGER.info("Libelle noeud : "+noeud.libelle());
            LOGGER.info("Description noeud : "+noeud.description());
        }
    }
    
    private void valideEtapeIntermediaire(INoeudArbre noeud) {
        Fraction probaSomme = new Fraction(0);
        for(INoeudArbre enfant :noeud.enfants()) {
            probaSomme = probaSomme.add(enfant.getProbabiliteNoeud());
            Assertions.assertThat(enfant.getProbabiliteConditionnelle()).isEqualTo(noeud.getProbabiliteConditionnelle().multiply(enfant.getProbabiliteNoeud()));
        }
        assertThat(probaSomme).isEqualTo(ENSEMBLE);
    }
}

On vérifie la cohérence de l'arbre et que l'on a la probabilité attendue, ainsi qu'au final le bon pool de dé.
On retourne l'arbre pour vérifier d'autres trucs (comme les blessures à la fin).

Et ainsi, les marines peuvent tirer sur les nouveaux termagants:
Code:
package com.calculateur.warhammer.calcul.mort.arbre.calcul;

import org.apache.commons.math3.fraction.Fraction;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;

import com.calculateur.warhammer.base.exception.FunctionnalExeption;
import com.calculateur.warhammer.calcul.mort.arbre.ENatureNoeud;
import com.calculateur.warhammer.calcul.mort.arbre.INoeudArbre;
import com.calculateur.warhammer.calcul.mort.arbre.calcul.builder.space.marine.SpaceMarineBuilderAttaque;
import com.calculateur.warhammer.calcul.mort.arbre.calcul.builder.tyranide.TermagantBuilderDefense;
import com.calculateur.warhammer.calcul.mort.arbre.data.IDataCalculProbabilite;
import com.calculateur.warhammer.calcul.mort.arbre.data.RecordDataCalculProbabilite;
import com.calculateur.warhammer.calcul.test.utils.FractionCheminBuilder;
import com.calculateur.warhammer.data.action.IContexteAction;
import com.calculateur.warhammer.data.enumeration.EBlessure;
import com.calculateur.warhammer.data.enumeration.EGestionDe;
import com.calculateur.warhammer.data.enumeration.EMouvement;
import com.calculateur.warhammer.data.enumeration.ESimule;
import com.calculateur.warhammer.data.identifiable.IBatiment;
import com.calculateur.warhammer.data.identifiable.batiment.RecordBatiment;
import com.calculateur.warhammer.data.regles.detachement.space.marine.ESermentInstantChoix;

public class SpaceMarineVsTermagantTirTest extends AbstractCalculArbreTest{

    @Test
    public void testMarineImmobileTermagantImmobileDecouvertLesDeux12ps() throws FunctionnalExeption{
        IContexteAction contexteAction = getContexteDecouvert(EMouvement.IMMOBILE);
        
        IDataCalculProbabilite data = getData(contexteAction);
        
        Fraction probaTouche = new Fraction(5, 6);
        Fraction probaBlesse = new Fraction(2, 3);
        Fraction probaRateSauvegarde = new Fraction(5,6);
        Fraction probaAttendu = FractionCheminBuilder.getInstance().addFraction(probaTouche).addFraction(probaBlesse).addFraction(probaRateSauvegarde).build();
        
        Integer reussite = 10;
        
        INoeudArbre racine = doTestStandard(data, probaAttendu, reussite);
        valideBlessuresSansRelances(racine);
    }
    
    @Test
    public void testMarineMouvementNormalTermagantImmobileDecouvertLesDeux12ps() throws FunctionnalExeption{
        IContexteAction contexteAction = getContexteDecouvert(EMouvement.NORMAL);
        
        IDataCalculProbabilite data = getData(contexteAction);
        
        Fraction probaTouche = new Fraction(2, 3);
        Fraction probaBlesse = new Fraction(2, 3);
        Fraction probaRateSauvegarde = new Fraction(5,6);
        Fraction probaAttendu = FractionCheminBuilder.getInstance().addFraction(probaTouche).addFraction(probaBlesse).addFraction(probaRateSauvegarde).build();
        
        Integer reussite = 8;
        
        INoeudArbre racine = doTestStandard(data, probaAttendu, reussite);
        valideBlessuresSansRelances(racine);
    }
    
    @Test
    public void testMarineImmobileTermagantImmobileMarineCouvertEtageTermagantDecouvertLesDeux12ps() throws FunctionnalExeption{
        IContexteAction contexteAction = getContexteBatiment(new RecordBatiment(true, true), new RecordBatiment(false, false));
        
        IDataCalculProbabilite data = getData(contexteAction);
        
        Fraction probaTouche = new Fraction(5, 6);
        Fraction probaBlesse = new Fraction(2, 3);
        Fraction probaAttendu = FractionCheminBuilder.getInstance().addFraction(probaTouche).addFraction(probaBlesse).build();
        
        Integer reussite = 12;
        
        INoeudArbre racine = doTestStandard(data, probaAttendu, reussite);
        valideBlessuresSansRelances(racine);
    }
    
    @Test
    public void testMarineImmobileTermagantImmobileMarineDecouvertTermagantCouvert12ps() throws FunctionnalExeption{
        IContexteAction contexteAction = getContexteBatiment(new RecordBatiment(false, false), new RecordBatiment(true, false));
        
        IDataCalculProbabilite data = getData(contexteAction);
        
        Fraction probaTouche = new Fraction(5, 6);
        Fraction probaBlesse = new Fraction(2, 3);
        Fraction probaRateSauvegarde = new Fraction(2,3);
        Fraction probaAttendu = FractionCheminBuilder.getInstance().addFraction(probaTouche).addFraction(probaBlesse).addFraction(probaRateSauvegarde).build();
        
        Integer reussite = 8;
        
        INoeudArbre racine = doTestStandard(data, probaAttendu, reussite);
        valideBlessuresSansRelances(racine);
    }
    
    @Test
    public void testMarineImmobileTermagantImmobileMarineRuineEtageTermagantRuine12ps() throws FunctionnalExeption{
        IContexteAction contexteAction = getContexteBatiment(new RecordBatiment(true, true), new RecordBatiment(true, false));
        
        IDataCalculProbabilite data = getData(contexteAction);
        
        Fraction probaTouche = new Fraction(5, 6);
        Fraction probaBlesse = new Fraction(2, 3);
        Fraction probaRateSauvegarde = new Fraction(5,6);
        Fraction probaAttendu = FractionCheminBuilder.getInstance().addFraction(probaTouche).addFraction(probaBlesse).addFraction(probaRateSauvegarde).build();
        
        Integer reussite = 10;
        
        INoeudArbre racine = doTestStandard(data, probaAttendu, reussite);
        valideBlessuresSansRelances(racine);
    }
    
    private void valideBlessuresSansRelances(INoeudArbre racine) {
        int nbNoeudReussite = 0;
        for(INoeudArbre noeud:racine.arbre()) {
            if(noeud.getNatureNoeud() == ENatureNoeud.REUSSITE) {
                nbNoeudReussite++;
                Assertions.assertThat(noeud.mapBlessuresAleatoires()).isEmpty();
                Assertions.assertThat(noeud.mapBlessure()).hasSize(1);
                Assertions.assertThat(noeud.mapBlessure()).containsKey(EBlessure.NORMALES);
                Integer nombreBlessure = noeud.mapBlessure().get(EBlessure.NORMALES);
                Assertions.assertThat(nombreBlessure).isEqualTo(1);
            }else {
                Assertions.assertThat(noeud.mapBlessure()).isEmpty();
            }
        }
        Assertions.assertThat(nbNoeudReussite).isEqualTo(1);
    }
    
    @Test
    public void testMarineImmobileTermagantImmobileDecouvertLesDeux12psMarineSermentInstant() throws FunctionnalExeption{
        IContexteAction contexteAction = getContexteDecouvert(EMouvement.IMMOBILE);
        
        IDataCalculProbabilite data = getData(contexteAction,ESermentInstantChoix.OUI);
        
        Fraction probaTouche = new Fraction(5, 6);
        Fraction probaEchecTouche = new Fraction(1,6);
        Fraction probaBlesse = new Fraction(2, 3);
        Fraction probaEchecBlesse = new Fraction(1,3);
        Fraction probaRateSauvegarde = new Fraction(5,6);
        
        //Reussit tout
        Fraction chemin1 = FractionCheminBuilder.getInstance().addFraction(probaTouche).addFraction(probaBlesse).addFraction(probaRateSauvegarde).build();
        //Rate seulement touche
        Fraction chemin2 = FractionCheminBuilder.getInstance().addFraction(probaEchecTouche).addFraction(probaTouche).addFraction(probaBlesse).addFraction(probaRateSauvegarde).build();
        //Rate seulement blessure
        Fraction chemin3 = FractionCheminBuilder.getInstance().addFraction(probaTouche).addFraction(probaEchecBlesse).addFraction(probaBlesse).addFraction(probaRateSauvegarde).build();
        //Rate touche et blessure
        Fraction chemin4 = FractionCheminBuilder.getInstance().addFraction(probaEchecTouche).addFraction(probaTouche).addFraction(probaEchecBlesse).addFraction(probaBlesse).addFraction(probaRateSauvegarde).build();
                
        Integer reussite = 15;
        
        Fraction probaAttendu = chemin1.add(chemin2).add(chemin3).add(chemin4);
        INoeudArbre racine = doTestStandard(data, probaAttendu, reussite);
        valideBlessuresAvecRelances(racine);
    }
    
    private void valideBlessuresAvecRelances(INoeudArbre racine) {
        int nbNoeudReussite = 0;
        for(INoeudArbre noeud:racine.arbre()) {
            if(noeud.getNatureNoeud() == ENatureNoeud.REUSSITE) {
                nbNoeudReussite++;
                Assertions.assertThat(noeud.mapBlessuresAleatoires()).isEmpty();
                Assertions.assertThat(noeud.mapBlessure()).hasSize(1);
                Assertions.assertThat(noeud.mapBlessure()).containsKey(EBlessure.NORMALES);
                Integer nombreBlessure = noeud.mapBlessure().get(EBlessure.NORMALES);
                Assertions.assertThat(nombreBlessure).isEqualTo(1);
            }else {
                Assertions.assertThat(noeud.mapBlessure()).isEmpty();
            }
        }
        Assertions.assertThat(nbNoeudReussite).isEqualTo(4);
    }
    
    private IDataCalculProbabilite getData(IContexteAction contexteAction) {
        return getData(contexteAction, ESermentInstantChoix.NON);
    }
    
    private IDataCalculProbabilite getData(IContexteAction contexteAction,ESermentInstantChoix choix) {
        SpaceMarineBuilderAttaque builderAttaquant = SpaceMarineBuilderAttaque.getInstance(contexteAction, 10);
        builderAttaquant.addBatiment(contexteAction.getBatimentAttaquant());
        builderAttaquant.addSermentInstant(choix);
        
        TermagantBuilderDefense builderDefenseur = TermagantBuilderDefense.getInstance(contexteAction, 10);
        builderDefenseur.addBatiment(contexteAction.getBatimentDefenseur());
        
        return new RecordDataCalculProbabilite(contexteAction, builderAttaquant.build(), builderDefenseur.build(), EGestionDe.SIMULATION_OPTIMISTE, EGestionDe.SIMULATION_OPTIMISTE,EGestionDe.SIMULATION_OPTIMISTE);
    }

    private IContexteAction getContexteDecouvert(EMouvement mouvementAttaquant) {
        return getContexteAction(mouvementAttaquant, new RecordBatiment(false, false), new RecordBatiment(false, false));
    }
    
    private IContexteAction getContexteBatiment(IBatiment batimentAttaquant,IBatiment batimentDefenseur) {
        return getContexteAction(EMouvement.IMMOBILE, batimentAttaquant, batimentDefenseur);
    }
    
    private IContexteAction getContexteAction(EMouvement mouvementAttaquant,IBatiment batimentAttaquant,IBatiment batimentDefenseur) {
        return ContextActionForTestProbaBuilder.getInstance()
                .addSimule(ESimule.TIR_PHASE_TIR)
                .addNumeroTour(2)
                .addEffectifInitialAttaquant(10)
                .addNombreAttaquant(10)
                .addMouvementAttaquant(mouvementAttaquant)
                .addBatimentAttaquant(batimentAttaquant)
                .addNombreDefenseur(10)
                .addMouvementDefenseur(EMouvement.IMMOBILE)
                .addBatimentDefenseur(batimentDefenseur)
                .addDistanceEntreBelligerant(12.0)
                .build();
    }
}
Reply


Messages In This Thread
Projet Calculateur - by Philou - 12-09-2022, 09:47 AM
RE: Projet Calculateur - by Philou - 12-09-2022, 09:52 AM
RE: Projet Calculateur - by Philou - 17-09-2022, 09:14 PM
RE: Projet Calculateur - by Philou - 25-09-2022, 07:26 AM
RE: Projet Calculateur - by Philou - 25-09-2022, 08:54 AM
RE: Projet Calculateur - by Philou - 03-10-2022, 10:54 AM
RE: Projet Calculateur - by Philou - 16-10-2022, 11:36 AM
RE: Projet Calculateur - by Philou - 24-10-2022, 01:08 PM
RE: Projet Calculateur - by Philou - 25-10-2022, 09:52 AM
RE: Projet Calculateur - by sdm - 25-10-2022, 11:06 PM
RE: Projet Calculateur - by Philou - 25-10-2022, 11:23 PM
RE: Projet Calculateur - by Philou - 26-10-2022, 03:09 PM
RE: Projet Calculateur - by Philou - 25-10-2022, 11:25 PM
RE: Projet Calculateur - by Philou - 06-11-2022, 05:27 PM
RE: Projet Calculateur - by Philou - 19-11-2022, 10:36 AM
RE: Projet Calculateur - by Philou - 23-11-2022, 08:34 AM
RE: Projet Calculateur - by Philou - 24-11-2022, 08:49 PM
RE: Projet Calculateur - by Philou - 04-12-2022, 06:57 PM
RE: Projet Calculateur - by Philou - 11-12-2022, 12:11 PM
RE: Projet Calculateur - by Philou - 18-12-2022, 06:47 PM
RE: Projet Calculateur - by Philou - 19-12-2022, 09:05 PM
RE: Projet Calculateur - by Philou - 03-01-2023, 09:34 PM
RE: Projet Calculateur - by Philou - 07-01-2023, 06:36 PM
RE: Projet Calculateur - by Philou - 01-02-2023, 08:21 PM
RE: Projet Calculateur - by Philou - 16-02-2023, 08:31 PM
RE: Projet Calculateur - by Gaeriel - 17-02-2023, 10:56 PM
RE: Projet Calculateur - by Philou - 17-02-2023, 11:32 PM
RE: Projet Calculateur - by Philou - 05-03-2023, 05:45 PM
RE: Projet Calculateur - by Philou - 06-03-2023, 08:55 PM
RE: Projet Calculateur - by Philou - 08-03-2023, 08:28 PM
RE: Projet Calculateur - by Philou - 12-03-2023, 07:56 AM
RE: Projet Calculateur - by Philou - 23-03-2023, 06:44 PM
RE: Projet Calculateur - by Philou - 28-03-2023, 08:58 PM
RE: Projet Calculateur - by Philou - 27-04-2023, 08:05 PM
RE: Projet Calculateur - by Philou - 30-04-2023, 10:29 AM
RE: Projet Calculateur - by Philou - 02-05-2023, 08:03 AM
RE: Projet Calculateur - by Philou - 19-05-2023, 11:36 AM
RE: Projet Calculateur - by Philou - 19-05-2023, 05:44 PM
RE: Projet Calculateur - by Philou - 20-05-2023, 09:10 PM
RE: Projet Calculateur - by Philou - 22-06-2023, 07:38 AM
RE: Projet Calculateur - by Philou - 24-06-2023, 07:09 AM
RE: Projet Calculateur - by Philou - 26-06-2023, 07:44 PM
RE: Projet Calculateur - by Philou - 28-06-2023, 07:09 AM
RE: Projet Calculateur - by Philou - 28-06-2023, 07:43 PM
RE: Projet Calculateur - by Philou - 30-06-2023, 07:22 PM
RE: Projet Calculateur - by Philou - 08-08-2023, 07:54 PM
RE: Projet Calculateur - by Philou - 19-08-2023, 10:30 AM
RE: Projet Calculateur - by Philou - 19-08-2023, 06:20 PM
RE: Projet Calculateur - by Philou - 20-08-2023, 10:17 AM
RE: Projet Calculateur - by Philou - 22-01-2024, 09:02 PM
RE: Projet Calculateur - by Philou - 09-05-2024, 10:21 AM
RE: Projet Calculateur - by Philou - 11-05-2024, 05:41 PM
RE: Projet Calculateur - by Philou - 25-05-2024, 08:41 AM
RE: Projet Calculateur - by Philou - 24-04-2025, 04:09 PM

Forum Jump:


Users browsing this thread: 1 Guest(s)