Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Projet Calculateur
#23
Et maintenant, la sauvegarde qui s'est révélé relativement facile à traité (TU compris).

Pour commencé, j'ai défini l'interface:
Code:
package com.calculateur.warhammer.calcul.mort.sauvegarde;

import java.util.Optional;

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;

/**
* Calcule la sauvegarde d'une figururine.
* @author phili
*
*/
public interface ICalculSauvegarde<A extends IArme> {

    /**
     *
     * @param attaquant Attaquant effectuant l'action
     * @param defenseur Défenseur effectuant l'action
     * @param contexteAction Contexte de l'action
     * @param bonusPA Bonus supplémentaire à la PA d'armure (peut-être null).
     * @return La sauvegarde d'armure (vide si pas de sauvegarde).
     */
    Optional<Integer> getSauvegarde(IConstituantAttaquant<A> attaquant,IConstituantDefenseur defenseur,IContexteAction<A> contexteAction,Integer bonusPA);
}
Notez que l'on a un optional, étant donné qu'il se peut qu'il n'y ait pas de sauvegarde. On ajoute aussi le bonus de PA (d'armure) vu que certaines armées, comme les SDB augmentent la PA de 1 sur 6+ au tir. Le bonus dépend donc du jet d'avant.

Comme une sauvegarde est comprise entre 2 et 6, on a donc un traitement pour ramener dans la bonne fourchette:
Code:
package com.calculateur.warhammer.calcul.mort.sauvegarde;

import java.util.Optional;

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;

/**
* Template Methode permettant d'ajuster la sauvegarde entre 2+ et 6+.
* @author phili
*
* @param <A>
*/
public abstract class AbstractCalculSauvegarde<A extends IArme> implements ICalculSauvegarde<A>{

    private static final Integer SAUVEGARDE_ARMURE_MAXIMUM = 6;
    
    private static final Integer SAUVEGARDE_ARMURE_MINIMUM = 2;
    
    protected AbstractCalculSauvegarde() {
    }
    
    @Override
    public Optional<Integer> getSauvegarde(IConstituantAttaquant<A> attaquant, IConstituantDefenseur defenseur,
            IContexteAction<A> contexteAction, Integer bonusPA) {
        Optional<Integer> sauvegardeBase = getSauvegardeBase(attaquant, defenseur, contexteAction, bonusPA);
        return (sauvegardeBase.isPresent())?ajusteSauvegarde(sauvegardeBase.get()):sauvegardeBase;
    }
    
    protected abstract Optional<Integer> getSauvegardeBase(IConstituantAttaquant<A> attaquant,IConstituantDefenseur defenseur,IContexteAction<A> contexteAction,Integer bonusPA);
    
    private Optional<Integer> ajusteSauvegarde(Integer sauvegardeBase){
        Integer sauvegarde;
        if(sauvegardeBase < SAUVEGARDE_ARMURE_MINIMUM) {
            sauvegarde = SAUVEGARDE_ARMURE_MINIMUM;
        }else if(sauvegardeBase > SAUVEGARDE_ARMURE_MAXIMUM) {
            sauvegarde = null;
        }else {
            sauvegarde = sauvegardeBase;
        }
        return Optional.ofNullable(sauvegarde);
    }
}

Reste à implémenter pour les cas connus (l'invulnérable a 2 cas suivant que ce soit sur le profil ou les règles comme c'est le cas des eldars noirs).

Code:
package com.calculateur.warhammer.calcul.mort.sauvegarde;

import java.util.Optional;

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;

/**
* Calcul de la sauvegarde d'armure
* @author phili
*
* @param <A>
*/
public class CalculSauvegardeArmure<A extends IArme> extends AbstractCalculSauvegarde<A>{

    private static final Integer MAXIMUM_PA = 0;
    private static final Integer BONUS_BASE_PA = 0;
    
    @Override
    protected Optional<Integer> getSauvegardeBase(IConstituantAttaquant<A> attaquant, IConstituantDefenseur defenseur,
            IContexteAction<A> contexteAction, Integer bonusPA) {
        Integer sauvegardeBase = defenseur.getProfil().getSauvegarde();
        return (sauvegardeBase != null)?Optional.of(getSauvegarde(sauvegardeBase, attaquant, defenseur, bonusPA)) :Optional.empty();
    }
    
    private Integer getSauvegarde(Integer sauvegardeBase,IConstituantAttaquant<A> attaquant,IConstituantDefenseur defenseur,Integer bonusPA) {
        Integer pa = getPA(attaquant, defenseur, bonusPA);
        
        boolean isCouvert = defenseur.getRegles().isSauvegardeCouvert() && !attaquant.getRegles().isIgnoreSauvegardeCouvert();
        Integer bonusCouvert = isCouvert?-1:0;
        
        Integer bonusDefenseurSauvegarde = defenseur.getRegles().getBonusSauvegardeArmure();
        Integer bonusDefenseurSauvegardeCalcul = (bonusDefenseurSauvegarde != null)?bonusDefenseurSauvegarde:0;
        
        return (sauvegardeBase + bonusCouvert + bonusDefenseurSauvegardeCalcul) - pa;
    }
    
    private Integer getPA(IConstituantAttaquant<A> attaquant,IConstituantDefenseur defenseur,Integer bonusPA) {
        Integer paArme = attaquant.getArme().getPA();
        Integer paArmeCalcul = (paArme != null)?paArme:MAXIMUM_PA;
        
        Integer bonusPARegle = attaquant.getRegles().getBonusPA();
        Integer bonusPaRegleCalcul = (bonusPARegle != null)?bonusPARegle:BONUS_BASE_PA;
        
        Integer reductionPA = defenseur.getRegles().getReductionPA();
        Integer reductionPACalcul = (reductionPA != null)?reductionPA:BONUS_BASE_PA;
        
        Integer bonusPACalcul = (bonusPA != null)?bonusPA:BONUS_BASE_PA;
        
        Integer pa = paArmeCalcul + bonusPaRegleCalcul + reductionPACalcul + bonusPACalcul;
        
        return (pa < MAXIMUM_PA)?pa:MAXIMUM_PA;
    }

}

Code:
package com.calculateur.warhammer.calcul.mort.sauvegarde;

import java.util.Optional;

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;

/**
* Calcul de la sauvegarde démoniaque
* @author phili
*
*/
public class CalculSauvegardeDemoniaque<A extends IArme> extends AbstractCalculSauvegarde<A>{

    @Override
    protected Optional<Integer> getSauvegardeBase(IConstituantAttaquant<A> attaquant, IConstituantDefenseur defenseur,
            IContexteAction<A> contexteAction, Integer bonusPA) {
        Optional<Integer> oSauvegarde;
        if(contexteAction.getSimule().isActionTir()) {
            oSauvegarde = Optional.ofNullable(defenseur.getProfil().getSauvegardeDemoniaqueTir());
        }else {
            oSauvegarde = Optional.ofNullable(defenseur.getProfil().getSauvegardeDemoniaqueCorpsACorps());
        }
        return oSauvegarde;
    }

}

Code:
package com.calculateur.warhammer.calcul.mort.sauvegarde;

import java.util.Optional;

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;

/**
* Calcul de la sauvegarde invulnérable par rapport au profil.
* @author phili
*
*/
public class CalculSauvegardeInvulnerableProfil<A extends IArme> extends AbstractCalculSauvegarde<A>{

    @Override
    protected Optional<Integer> getSauvegardeBase(IConstituantAttaquant<A> attaquant, IConstituantDefenseur defenseur,
            IContexteAction<A> contexteAction, Integer bonusPA) {
        return attaquant.getRegles().isIgnoreSauvegardeInvulnerable()?Optional.empty():Optional.ofNullable(defenseur.getProfil().getSauvegardeInvulnerable());
    }
}

Code:
package com.calculateur.warhammer.calcul.mort.sauvegarde;

import java.util.Optional;

import com.calculateur.warhammer.data.action.IContexteAction;
import com.calculateur.warhammer.data.identifiable.IArme;
import com.calculateur.warhammer.data.regles.IRegleDefense;
import com.calculateur.warhammer.data.unite.IConstituantAttaquant;
import com.calculateur.warhammer.data.unite.IConstituantDefenseur;

/**
* Calcul de la sauvegarde invulnérable due aux règles
* @author phili
*
* @param <A>
*/
public class CalculSauvegardeInvulnerableRegle<A extends IArme> extends AbstractCalculSauvegarde<A>{

    @Override
    protected Optional<Integer> getSauvegardeBase(IConstituantAttaquant<A> attaquant, IConstituantDefenseur defenseur,
            IContexteAction<A> contexteAction, Integer bonusPA) {
        return attaquant.getRegles().isIgnoreSauvegardeInvulnerable()?Optional.empty():getSauvegardeFromRegles(defenseur.getRegles());
    }

    private Optional<Integer> getSauvegardeFromRegles(IRegleDefense regle){
        return Optional.ofNullable(regle.getSauvegardeInvulnerable()).filter(s -> s > 0);
    }
}

Evidement, hors de question de boucler sur toutes les sauvegardes qui existent.

On va donc utiliser un Design Pattern du GOFF pour ne voir qu'un seul calcul, le Design Pattern Décorateur:
Code:
package com.calculateur.warhammer.calcul.mort.sauvegarde;

import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;

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;

/**
* Décorateur pour calculer toutes les sauvegardes et prendre la meilleure.
* @author phili
*
* @param <A>
*/
public class CalculSauvegardeDecorateur<A extends IArme> implements ICalculSauvegarde<A>{

    private final List<ICalculSauvegarde<A>> sauvegardes;
    
    public CalculSauvegardeDecorateur(List<ICalculSauvegarde<A>> sauvegardes) {
        this.sauvegardes = sauvegardes;
    }

    @Override
    public Optional<Integer> getSauvegarde(IConstituantAttaquant<A> attaquant, IConstituantDefenseur defenseur,
            IContexteAction<A> contexteAction, Integer bonusPA) {
        OptionalInt sRes =    sauvegardes.stream().map(cs -> cs.getSauvegarde(attaquant, defenseur, contexteAction, bonusPA))
                 .filter(Optional::isPresent).filter(os -> os.get() > 0).mapToInt(Optional::get).min();
         return sRes.isPresent()?Optional.of(sRes.getAsInt()):Optional.empty();
    }

}

Reste à fabriquer tout ça avec une factory (autre Design pattern du GOFF):
Code:
package com.calculateur.warhammer.calcul.mort.factory.sauvegarde;

import com.calculateur.warhammer.calcul.mort.factory.exception.SimulationException;
import com.calculateur.warhammer.calcul.mort.sauvegarde.ICalculSauvegarde;
import com.calculateur.warhammer.data.enumeration.ESimule;
import com.calculateur.warhammer.data.identifiable.IArmeDeCorpsACorps;
import com.calculateur.warhammer.data.identifiable.IArmeDeTir;

/**
* Factory pour instancier les calcul de sauvegarde
* @author phili
*
*/
public interface IFactorySauvegarde {

    /**
     *
     * @param simule Ce qui est simulé
     * @return Le calcul de la sauvegarde
     * @throws SimulationException Si ce qui est simulé est une action de mêlée
     */
    ICalculSauvegarde<IArmeDeTir> calculSauvegardeTir(ESimule simule)throws SimulationException;
    
    /**
     *
     * @param simule Ce qui est simulé
     * @return Le calcul de la sauvegarde
     * @throws SimulationException Si ce qui est simulé est une action de tir
     */
    ICalculSauvegarde<IArmeDeCorpsACorps> calculSauvegardeCorpsACorp(ESimule simule)throws SimulationException;
    
}

Et l'implémentation:
Code:
package com.calculateur.warhammer.calcul.mort.factory.sauvegarde;

import java.util.Arrays;

import com.calculateur.warhammer.calcul.mort.factory.exception.SimulationException;
import com.calculateur.warhammer.calcul.mort.factory.utils.FactoryUtils;
import com.calculateur.warhammer.calcul.mort.sauvegarde.CalculSauvegardeDemoniaque;
import com.calculateur.warhammer.calcul.mort.sauvegarde.CalculSauvegardeArmure;
import com.calculateur.warhammer.calcul.mort.sauvegarde.CalculSauvegardeDecorateur;
import com.calculateur.warhammer.calcul.mort.sauvegarde.CalculSauvegardeInvulnerableProfil;
import com.calculateur.warhammer.calcul.mort.sauvegarde.CalculSauvegardeInvulnerableRegle;
import com.calculateur.warhammer.calcul.mort.sauvegarde.ICalculSauvegarde;
import com.calculateur.warhammer.data.enumeration.ESimule;
import com.calculateur.warhammer.data.identifiable.IArmeDeCorpsACorps;
import com.calculateur.warhammer.data.identifiable.IArmeDeTir;

public class FactorySauvegarde implements IFactorySauvegarde{

    private final ICalculSauvegarde<IArmeDeTir> calculTir;

    private final ICalculSauvegarde<IArmeDeCorpsACorps> calculCorpsACorps;
    
    public FactorySauvegarde() {
        calculTir = new CalculSauvegardeDecorateur<>(Arrays.asList(
                new CalculSauvegardeArmure<>(),
                new CalculSauvegardeDemoniaque<>(),
                new CalculSauvegardeInvulnerableProfil<>(),
                new CalculSauvegardeInvulnerableRegle<>()));
        calculCorpsACorps = new CalculSauvegardeDecorateur<>(Arrays.asList(
                new CalculSauvegardeArmure<>(),
                new CalculSauvegardeDemoniaque<>(),
                new CalculSauvegardeInvulnerableProfil<>(),
                new CalculSauvegardeInvulnerableRegle<>()));
    }
    
    @Override
    public ICalculSauvegarde<IArmeDeTir> calculSauvegardeTir(ESimule simule) throws SimulationException {
        FactoryUtils.valideActionTir(simule);
        return calculTir;
    }

    @Override
    public ICalculSauvegarde<IArmeDeCorpsACorps> calculSauvegardeCorpsACorp(ESimule simule) throws SimulationException {
        FactoryUtils.valideActionCorpsACorps(simule);
        return calculCorpsACorps;
    }

}

On n'a plus qu'à modifier le paramétrage pour Spring.
Code:
package com.calculateur.warhammer.calcul.mort.parametres;

import com.calculateur.warhammer.calcul.mort.factory.sauvegarde.IFactorySauvegarde;
import com.calculateur.warhammer.calcul.mort.factory.validation.IFactoryValidation;

/**
* Paramètres pour fabriquer les factory nécessaires au calcul.
* @author phili
*
*/
public interface IParametres {

    IFactoryValidation getFactoryValidation();
    
    IFactorySauvegarde getFactorySauvegarde();
}
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)