Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Projet Calculateur
#11
Malheureusement, MySQL (devenu Maria DB depuis) a été utilisé dans des applications techniques.

Boidleau
Reply
#12
Un ingénieur d'Oracle qui a travaillé sur MySQL explique que MySQL est ... à chier Boidleau 

https://mysql.developpez.com/actu/329296...selon-lui/
Reply
#13
(25-10-2022, 11:23 PM)Philou Wrote: Malheureusement, MySQL (devenu Maria DB depuis) a été utilisé dans des applications techniques.

Boidleau
Je devrais dire critiques....
Reply
#14
J'ai enfin un client (ou début de client) pour mon projet.

Donc une bonne vielle IHM cette fois ci en JavaFX.

.jpg   ihm_cl_1.jpg (Size: 153.53 KB / Downloads: 14)

C'est dynamique selon les choix, et c'est traduisible.

.jpg   ihm_cl_2.jpg (Size: 135.13 KB / Downloads: 4)

Et un tooltip rappelle la règle.

.jpg   ihm_cl_3.jpg (Size: 150.59 KB / Downloads: 6)


Fonctionne avec un serveur derrière, évidement.
Reply
#15
Déception pour la Raven Guard. Autant pour le trait de chapitre, il est super bien. Mais le bonus en doctrine tactique, il est super nul. D'autant que les scouts sont un choix d'élite en ce moment Doom
Reply
#16
J'ai enfin implémenté l'ensemble des règles spaces marines (seulement les traits de chapitres pour les Black Templar et la Deathwatch) et mon dieu, qu'est-ce qu'il y en a... Sweatdrop
Reply
#17
J'en profite pour cracher sur certaines personnes (dont je tairai le nom) pour dire que dans le projet data (c'est le métier), j'ai 556 tests unitaires avec une couverture de 88,5%.
Reply
#18
En passant (dans data) à 745 tests, je suis passé à une couverture de 94,6%.
Reply
#19
Dans le projet data, après j'arrive à une couverture de 95,5% après avoir codé 771 tests unitaires (ce qui m'a permis de simplifier le code, et trouver des bugs au passage).
Reply
#20
40K, ce jeu où il y a trop de règles Mur

Revenant enfin sur le métier, dans le calcul (projet calcul, il était temps), j'ai essayé de décomposer les étapes (d'abord déterminer le jet pour toucher, pour blesser ...).

Mais je suis arrivé à un problème: il faut vérifier que celui qui utilise l'API ne donne pas en entrée de la merde.

Par exemple, que l'on ne simule pas un phase de tir en mêlée alors que l'on est avec une arme à tir rapide (encore un problème, le Dark Angel peut en mêlée avec une arme à tir rapide ou une arme d'assaut en doctrine tactique) Mur

Et mine de rien, il y a plein de choses à valider Injures .

Du coup, j'ai re-décomposé et je me suis occupé que de la validation.

Pour commencé, comme Java est un bon langage, j'ai commencé par définir de annotations pour savoir quoi valider lors des différents calculs:
Code:
package com.calculateur.warhammer.calcul.mort.validation.annotations;

/**
* Validation pour un corps à corps
* @author phili
*
*/
public @interface ValidationCorpsACorps {

}


Code:
package com.calculateur.warhammer.calcul.mort.validation.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* Si validation à la phase de tir
* @author phili
*
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidationPhaseTir {

}

Code:
package com.calculateur.warhammer.calcul.mort.validation.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
* Valmidation pour un tir de contre charge
* @author phili
*
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidationTirContreCharge {

}
Ce qui permettra de fabriquer une factory (Design Pattern du GOFF).

Du coup, il n'y a plus qu'à valider:
Code:
package com.calculateur.warhammer.calcul.mort.validation;

import com.calculateur.warhammer.calcul.mort.validation.exception.ValidationCalculException;
import com.calculateur.warhammer.data.action.IContexteAction;
import com.calculateur.warhammer.data.identifiable.IArme;
import com.calculateur.warhammer.data.unite.IConstituantAttaquant;
import com.calculateur.warhammer.data.unite.IConstituantDefenseur;

/**
* Validateur pour savoir si l'action calculé ou simulée est possible
* @author phili
*
* @param <A> Arme utilisée
*/
public interface IValidationCalcul <A extends IArme>{

    /**
     * Valide l'action simulée ou calculée
     * @param attaquant Attaquant effectuant l'attaque
     * @param defenseur Défenseur effectuant l'attaque
     * @param contexteAction Contexte de l'action
     * @throws ValidationCalculException Si l'action n'est pas possible
     */
    void valideCalcul(IConstituantAttaquant<A> attaquant,IConstituantDefenseur defenseur,IContexteAction<A> contexteAction)throws ValidationCalculException;
}

Avec un utilisateur qui verra un truc traduit:
Code:
package com.calculateur.warhammer.calcul.mort.validation.exception;

import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;

import com.calculateur.warhammer.base.traduction.ITraduction;

/**
* Exception lancée lorsque le calcul n'est pas possible
* @author phili
*
*/
@SuppressWarnings("all")
public class ValidationCalculException extends Exception implements ITraduction{

    /**
     *
     */
    private static final long serialVersionUID = 1L;

    private final String resources;
    
    private final Object[] objets;
    
    private final String key;
    
    private String message;
    
    public ValidationCalculException(String resources, Object[] objets, String key) {
        this.resources = resources;
        this.objets = objets;
        this.key = key;
    }

    @Override
    public ResourceBundle getResourceBundle(Locale locale) {
        return ResourceBundle.getBundle(resources, locale);
    }

    @Override
    public void traduireLibelles(Locale locale) {
        String messageToFormat = getResourceBundle(locale).getString(key);
        message = (objets != null)? MessageFormat.format(messageToFormat, objets):messageToFormat;
    }

    @Override
    public String getMessage() {
        return message != null?message:key;
    }
    
    public Object[] getObjets() {
        return objets;
    }
}
Et un test de base (toujours faire un TU):
Code:
package com.calculateur.warhammer.calcul.mort.validation;

import java.text.MessageFormat;
import java.util.Locale;
import java.util.ResourceBundle;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import com.calculateur.warhammer.calcul.mort.validation.exception.ValidationCalculException;
import com.calculateur.warhammer.data.action.IContexteAction;
import com.calculateur.warhammer.data.identifiable.IArme;
import com.calculateur.warhammer.data.identifiable.IProfil;
import com.calculateur.warhammer.data.regles.IRegleAttaque;
import com.calculateur.warhammer.data.unite.IConstituantAttaquant;
import com.calculateur.warhammer.data.unite.IConstituantDefenseur;
import com.calculateur.warhammer.data.unite.implementation.BasicConstituantUniteAttaquant;

@Execution(ExecutionMode.SAME_THREAD)
@ExtendWith(MockitoExtension.class)
public abstract class AbstractValidationTest <A extends IArme>{

    private Locale[] LOCALES =  {Locale.FRANCE,Locale.ENGLISH};
    
    private IConstituantAttaquant<A> attaquant;
    
    @Mock
    protected IProfil profilAttaquant;
    
    @Mock
    protected IRegleAttaque regleAttaquant;
    
    @Mock
    protected IContexteAction<A> contextAction;
    
    private final IValidationCalcul<A> validator;

    protected AbstractValidationTest(IValidationCalcul<A> validator) {
        this.validator = validator;
    }
    
    @BeforeEach
    public void beforeEach() {
        attaquant = new BasicConstituantUniteAttaquant<A>(profilAttaquant, null, null, getArme(), regleAttaquant);
    }
    
    protected abstract A getArme();
    
    protected void testValidationStandard(boolean isExceptionAttendue) {
        testValidationStandard(isExceptionAttendue, attaquant, contextAction);
    }
    
    protected void testValidationStandard(boolean isExceptionAttendue,IConstituantAttaquant<A> aAttaquant,IContexteAction<A> aContext) {
        testValidationStandard(isExceptionAttendue, aAttaquant, null,contextAction);
    }
    
    protected void testValidationStandard(boolean isExceptionAttendue,IConstituantAttaquant<A> aAttaquant,IConstituantDefenseur defenseur,IContexteAction<A> aContext) {
        try {
            validator.valideCalcul(aAttaquant,defenseur, aContext);
            Assertions.assertThat(isExceptionAttendue).isFalse();
        }catch(ValidationCalculException ex) {
            Assertions.assertThat(isExceptionAttendue).isTrue();
            valideException(ex);
        }
    }
    
    private void valideException(ValidationCalculException ex) {
        String key = ex.getMessage();
        Object[] params = ex.getObjets();
        Assertions.assertThat(key).isNotNull();
        ResourceBundle res;
        for(Locale locale:LOCALES) {
            res = ex.getResourceBundle(locale);
            ex.traduireLibelles(locale);
            Assertions.assertThat(ex.getMessage()).isEqualTo(MessageFormat.format(res.getString(key), params));
        }
    }
}

Soit pour savoir si on tir en mêlée:
Code:
package com.calculateur.warhammer.calcul.mort.validation;

import java.util.Set;

import com.calculateur.warhammer.calcul.mort.validation.annotations.ValidationPhaseTir;
import com.calculateur.warhammer.calcul.mort.validation.exception.ValidationCalculException;
import com.calculateur.warhammer.data.action.IContexteAction;
import com.calculateur.warhammer.data.enumeration.EProfil;
import com.calculateur.warhammer.data.identifiable.IArmeDeTir;
import com.calculateur.warhammer.data.unite.IConstituantAttaquant;
import com.calculateur.warhammer.data.unite.IConstituantDefenseur;

/**
* Validation si on peut tirer en mêlée
* @author phili
*
*/
@ValidationPhaseTir
public class ValidationPhaseTirMelee implements IValidationCalcul<IArmeDeTir>{

    @Override
    public void valideCalcul(IConstituantAttaquant<IArmeDeTir> attaquant,IConstituantDefenseur defenseur, IContexteAction<IArmeDeTir> contexteAction)
            throws ValidationCalculException {
        if(contexteAction.isZoneEngagement() &&
                !isVehiculeOuMonstre(attaquant.getProfil().getTypesProfils()) &&
                    !attaquant.getRegles().isPeutUtiliserArmePorteeEngagement(attaquant.getArme().getType())) {
            Object[] params = {attaquant.getArme().getType()};
            throw new ValidationCalculException(ValidationCalculUtil.RESOURCE_ERREUR_PHASE_TIR,params, "erreur.tir.melee");
        }
        
    }

    
    private boolean isVehiculeOuMonstre(Set<EProfil> typesProfils) {
        return typesProfils.contains(EProfil.VEHICULE) || typesProfils.contains(EProfil.MONSTRE);
    }
}

Ou si on peut charger après une retraite:
Code:
package com.calculateur.warhammer.calcul.mort.validation;

import com.calculateur.warhammer.calcul.mort.validation.annotations.ValidationCorpsACorps;
import com.calculateur.warhammer.calcul.mort.validation.exception.ValidationCalculException;
import com.calculateur.warhammer.data.action.IContexteAction;
import com.calculateur.warhammer.data.enumeration.ESimule;
import com.calculateur.warhammer.data.identifiable.IArme;
import com.calculateur.warhammer.data.unite.IConstituantAttaquant;
import com.calculateur.warhammer.data.unite.IConstituantDefenseur;

/**
* Valida si la charge est possible
* @author phili
*
*/
@ValidationCorpsACorps
public class ValidationChargePossible implements IValidationCalcul<IArme>{

    @Override
    public void valideCalcul(IConstituantAttaquant<IArme> attaquant,IConstituantDefenseur defenseur, IContexteAction<IArme> contexteAction)
            throws ValidationCalculException {
        if(contexteAction.getSimule() == ESimule.CORPS_A_CORPS_APRES_CHARGE && !attaquant.getRegles().isChargeApresTypeMouvement(contexteAction.getMouvementAttaquant())) {
            Object[] param = {contexteAction.getMouvementAttaquant()};
            throw new ValidationCalculException(ValidationCalculUtil.RESOURCE_ERREUR_CORPS_A_CORPS, param, "erreur.charge.impossible");
        }
    }

}
Evidement, tout ça est testé (avec d'autres validateurs) et les TU ont été écrit avant selon le principe du TDD.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)