18-04-2022, 09:41 PM
Le contrat:
L'implémentation:
Et le TU:
. Mais le TU, lui, il est bon !
Quote:package com.calculateur.warhammer.de;
import java.util.List;
import org.apache.commons.math3.fraction.Fraction;
/**
* Calcul et simulation sur un jet de dé
*
* @author phili
*
*/
public interface IJetDe {
/**
*
* @return Moyenne du jet de dé
*/
double moyenne();
/**
*
* @param nombreDe Nombre dé lancé
* @return La moyenne sur le nombre de dé
* @throws LanceDeException
*/
double moyenne(Integer nombreDe) throws LanceDeException;
/**
*
* @param nombreDe Nomnre dé lancé
* @param score Score à obtenir
* @return Score à obtenir
* @throws LanceDeException
*
*/
Fraction probabileScore(Integer nombreDe, Integer score) throws LanceDeException;
/**
*
* @param isLogiqueOptimiste Si vrai, privilégie les bon scores
* @param nombreLance Le nombre de dé lancé.
* @return La liste des dé obtenu
*/
List<IDe> simuleJet(boolean isLogiqueOptimiste, Integer nombreLance) throws LanceDeException;
/**
*
* @param score Score à obtenir
* @return La probabilité d'obtenir le score.
* @throws LanceDeException
*/
List<IDe> getLancePourScore(Integer score) throws LanceDeException;
}
L'implémentation:
Quote:package com.calculateur.warhammer.de;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.math3.fraction.Fraction;
import com.calculateur.warhammer.calcul.proba.ArbreProbabilite;
import com.calculateur.warhammer.calcul.proba.EvenementImplementation;
import com.calculateur.warhammer.calcul.proba.IArbreProbabilite;
import com.calculateur.warhammer.calcul.proba.IEvenement;
import com.calculateur.warhammer.calcul.proba.IProbabilite;
import com.calculateur.warhammer.calcul.proba.ProbabiliteException;
import com.calculateur.warhammer.calcul.proba.ProbabiliteImplementation;
import com.calculateur.warhammer.calcul.proba.SommeProbabilite;
/**
* Implementation pour les calcul et la simulation des jets de dés
*
* @author phili
*
*/
public class JetDeImplementation implements IJetDe {
private final List<IDe> resultatsPossibles;
public JetDeImplementation(List<IDe> resultatsPossibles) {
this.resultatsPossibles = resultatsPossibles;
}
@Override
public double moyenne() {
Fraction resultat = new Fraction(0);
Fraction rEtape;
Fraction pEtape;
Fraction mEtape;
for (IDe de : resultatsPossibles) {
rEtape = new Fraction(de.getResultat());
pEtape = de.getProbabilite();
mEtape = rEtape.multiply(pEtape);
resultat = resultat.add(mEtape);
}
return resultat.doubleValue();
}
@Override
public double moyenne(Integer nombreDe) throws LanceDeException {
verifieNombreLance(nombreDe);
return moyenne() * nombreDe.doubleValue();
}
@Override
public Fraction probabileScore(Integer nombreDe, Integer score) throws LanceDeException {
verifieNombreLance(nombreDe);
verifieScore(score, nombreDe);
try {
Map<Integer, Map<IEvenement, Integer>> mapMapScore = new HashMap<>();
IArbreProbabilite arbre = getArbreEtRemplirMap(mapMapScore, nombreDe);
Map<IEvenement, Integer> mapResultat = mapMapScore.get(nombreDe - 1);
SommeProbabilite probaSomme = new SommeProbabilite(
new EvenementImplementation("obetenir." + score + ".sur." + nombreDe + ".lancees"));
for (Entry<IEvenement, Integer> entry : mapResultat.entrySet()) {
if (entry.getValue() >= score) {
probaSomme.addProbabilite(
new ProbabiliteImplementation(entry.getKey(), arbre.getProbabilite(entry.getKey())));
}
}
return probaSomme.getProbabilite();
} catch (ProbabiliteException e) {
throw new LanceDeException(e);
}
}
@Override
public List<IDe> simuleJet(boolean isLogiqueOptimiste, Integer nombreLance) throws LanceDeException {
verifieNombreLance(nombreLance);
List<IDe> listeCalcul = new ArrayList<>();
listeCalcul.addAll(resultatsPossibles);
Collections.sort(listeCalcul, new ComparatorDe(isLogiqueOptimiste));
List<IDe> lReturn = new ArrayList<>();
if (nombreLance <= listeCalcul.size()) {
remplirJetPeuDe(lReturn, listeCalcul, nombreLance);
} else {
remplirPleinDes(lReturn, listeCalcul, nombreLance);
}
return lReturn;
}
@Override
public List<IDe> getLancePourScore(Integer score) throws LanceDeException {
verifieScore(score, 1);
List<IDe> lReturn = new ArrayList<>();
for (IDe de : resultatsPossibles) {
if (de.getResultat() >= score) {
lReturn.add(de);
}
}
return lReturn;
}
private IArbreProbabilite getArbreEtRemplirMap(Map<Integer, Map<IEvenement, Integer>> mapMapScore,
Integer nombreLance) throws ProbabiliteException {
Integer indiceLance = 0;
IEvenement eRacine = new EvenementImplementation("racine");
IEvenement eCourant;
IArbreProbabilite arbreProbabilite = new ArbreProbabilite(eRacine);
StringBuilder sbEvenement;
List<IEvenement> ePrecedents = new ArrayList<IEvenement>();
List<IEvenement> eSuivants = new ArrayList<>();
ePrecedents.add(eRacine);
List<IProbabilite> toAdd = new ArrayList<>();
Map<IEvenement, Integer> mapCourante;
Map<IEvenement, Integer> mapPrecedente;
Integer resultat;
while (indiceLance < nombreLance) {
eSuivants.clear();
for (IEvenement ePrecedent : ePrecedents) {
toAdd.clear();
for (IDe de : resultatsPossibles) {
sbEvenement = new StringBuilder();
sbEvenement.append(ePrecedent.getId());
sbEvenement.append(".");
sbEvenement.append(de.getId());
eCourant = new EvenementImplementation(sbEvenement.toString());
toAdd.add(new ProbabiliteImplementation(eCourant, de.getProbabilite()));
// Score
mapPrecedente = mapMapScore.get(indiceLance - 1);
resultat = (mapPrecedente != null) ? mapPrecedente.get(ePrecedent) : 0;
resultat = resultat + de.getResultat();
mapCourante = mapMapScore.computeIfAbsent(indiceLance, k -> new HashMap<>());
mapCourante.put(eCourant, resultat);
eSuivants.add(eCourant);
}
arbreProbabilite.addProbabilites(ePrecedent, toAdd);
}
indiceLance++;
ePrecedents.clear();
ePrecedents.addAll(eSuivants);
}
return arbreProbabilite;
}
private void remplirJetPeuDe(List<IDe> lReturn, List<IDe> iTravail, Integer nombreTirage) {
Integer increment = (nombreTirage > (iTravail.size() / 2)) ? 1 : 2;
int i = 0;
int nb = 0;
while (i < iTravail.size() && nb < nombreTirage) {
lReturn.add(iTravail.get(i));
i = i + increment;
nb++;
}
}
private void remplirPleinDes(List<IDe> lReturn, List<IDe> iTravail, Integer nombreTirage) {
Integer reste = nombreTirage;
Fraction score;
Integer nombre;
for (IDe de : iTravail) {
score = de.getProbabilite().multiply(new Fraction(nombreTirage));
nombre = score.getNumerator() / score.getDenominator();
for (int i = 0; i < nombre; i++) {
lReturn.add(de);
}
reste = reste - nombre;
}
if (reste > 0) {
for (int i = 0; i < reste; i++) {
lReturn.add(iTravail.get(0));
}
}
}
private void verifieNombreLance(Integer nombreDe) throws LanceDeException {
if (nombreDe == null) {
throw new LanceDeException(new NullPointerException("Le nombre de dé à lancer est null"));
}
if (nombreDe < 1) {
throw new LanceDeException(
"Il faut lancer au moins 1 D, et le nombre de lancé est strictrment positif (Nombre de lancé : "
+ nombreDe.toString() + ")");
}
}
private void verifieScore(Integer score, Integer nombreLance) throws LanceDeException {
if (score == null) {
throw new LanceDeException(new NullPointerException("Le score est null"));
}
Integer min = resultatsPossibles.stream().map(d -> d.getResultat()).toList().stream().min(Integer::compare)
.get();
Integer max = resultatsPossibles.stream().map(d -> d.getResultat()).toList().stream().max(Integer::compare)
.get();
if (score < (min * nombreLance)) {
throw new LanceDeException("Avec ce dé, le score minimum est " + min.toString()
+ " et on ne peut pas atteindre " + score.toString());
}
if (score > (max * nombreLance)) {
throw new LanceDeException("Avec ce dé, le score maximum est " + max.toString()
+ " et on ne peut pas atteindre " + score.toString());
}
}
}
Et le TU:
Quote:package com.calculateur.warhammer.de;Comme c'est long, j'avais fait une pause Mamar et, je me suis trompé en divisant par 2
import static org.junit.jupiter.api.Assertions.fail;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.math3.fraction.Fraction;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
public class JetDeImplementationTest {
private final IJetDe jetDe;
public JetDeImplementationTest() {
jetDe = new JetDeImplementation(Arrays.asList(D6.values()));
}
@Test
public void testMoyenne() {
Assertions.assertThat(jetDe.moyenne()).isEqualTo(3.5);
}
@Test
public void testMoyenneNombreDesNull() {
try {
jetDe.moyenne(null);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isInstanceOf(NullPointerException.class);
}
}
@Test
public void testMoyenneNombreNegatif() {
try {
jetDe.moyenne(-1);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isNull();
}
}
@Test
public void testMoyenne2D() {
try {
Assertions.assertThat(jetDe.moyenne(2)).isEqualTo(7.0);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testMoyenne3D() {
try {
Assertions.assertThat(jetDe.moyenne(3)).isEqualTo(10.5);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testMoyenne4D() {
try {
Assertions.assertThat(jetDe.moyenne(4)).isEqualTo(14.0);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testProbabileScoreNombreJetNull() {
try {
jetDe.probabileScore(null, 5);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isInstanceOf(NullPointerException.class);
}
}
@Test
public void testProbabileScoreNombreJetNegatif() {
try {
jetDe.probabileScore(-5, 5);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isNull();
}
}
@Test
public void testProbabileScoreScoreNull() {
try {
jetDe.probabileScore(3, null);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isInstanceOf(NullPointerException.class);
}
}
@Test
public void testProbabileScoreScoreNegatif() {
try {
jetDe.probabileScore(5, -5);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isNull();
}
}
@Test
public void testProbabileScoreScoreTropGrand() {
try {
jetDe.probabileScore(3, 25);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isNull();
}
}
@Test
public void testProbabileScoreSur2D() {
try {
Assertions.assertThat(jetDe.probabileScore(2, 9)).isEqualTo(new Fraction(5, 18));
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testProbabileScoreSur3D() {
try {
int score = 15;
int nb = 0;
int total = 6 * 6 * 6;
List<IDe> l1 = Arrays.asList(D6.values());
List<IDe> l2 = Arrays.asList(D6.values());
List<IDe> l3 = Arrays.asList(D6.values());
Integer eSomme;
for (IDe d1 : l1) {
for (IDe d2 : l2) {
for (IDe d3 : l3) {
eSomme = d1.getResultat() + d2.getResultat() + d3.getResultat();
if (eSomme >= score) {
nb++;
}
}
}
}
Assertions.assertThat(jetDe.probabileScore(3, score)).isEqualTo(new Fraction(nb, total));
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetNombreJetNull() {
try {
jetDe.simuleJet(true, null);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isInstanceOf(NullPointerException.class);
}
}
@Test
public void testSimuleJetNombreJetNegatif() {
try {
jetDe.simuleJet(true, -5);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isNull();
}
}
@Test
public void testSimuleJetOptimiste2D() {
try {
List<IDe> esperes = Arrays.asList(D6.D6_RESULTAT_6, D6.D6_RESULTAT_4);
List<IDe> resultats = jetDe.simuleJet(true, 2);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetPessimiste2D() {
try {
List<IDe> esperes = Arrays.asList(D6.D6_RESULTAT_1, D6.D6_RESULTAT_3);
List<IDe> resultats = jetDe.simuleJet(false, 2);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetOptimiste3D() {
try {
List<IDe> esperes = Arrays.asList(D6.D6_RESULTAT_6, D6.D6_RESULTAT_4, D6.D6_RESULTAT_2);
List<IDe> resultats = jetDe.simuleJet(true, 3);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetPessimiste3D() {
try {
List<IDe> esperes = Arrays.asList(D6.D6_RESULTAT_1, D6.D6_RESULTAT_3, D6.D6_RESULTAT_5);
List<IDe> resultats = jetDe.simuleJet(false, 3);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetPessimiste5D() {
try {
List<IDe> esperes = Arrays.asList(D6.D6_RESULTAT_1, D6.D6_RESULTAT_2, D6.D6_RESULTAT_3, D6.D6_RESULTAT_4,
D6.D6_RESULTAT_5);
List<IDe> resultats = jetDe.simuleJet(false, 5);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetOptimiste5D() {
try {
List<IDe> esperes = Arrays.asList(D6.D6_RESULTAT_6, D6.D6_RESULTAT_5, D6.D6_RESULTAT_4, D6.D6_RESULTAT_3,
D6.D6_RESULTAT_2);
List<IDe> resultats = jetDe.simuleJet(true, 5);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetPessimiste18D() {
try {
List<IDe> esperes = new ArrayList<>();
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
List<IDe> resultats = jetDe.simuleJet(false, 18);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetOptimiste18D() {
try {
List<IDe> esperes = new ArrayList<>();
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
List<IDe> resultats = jetDe.simuleJet(false, 18);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetPessimiste20D() {
try {
List<IDe> esperes = new ArrayList<>();
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
List<IDe> resultats = jetDe.simuleJet(false, 20);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testSimuleJetOptimiste20D() {
try {
List<IDe> esperes = new ArrayList<>();
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_6);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_5);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_4);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_3);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_2);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
esperes.add(D6.D6_RESULTAT_1);
List<IDe> resultats = jetDe.simuleJet(true, 20);
assertSimulation(esperes, resultats);
} catch (LanceDeException e) {
fail();
}
}
@Test
public void testLancePourScoreScoreNull() {
try {
jetDe.getLancePourScore(null);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isInstanceOf(NullPointerException.class);
}
}
@Test
public void testLancePourScoreScoreNegatif() {
try {
jetDe.getLancePourScore(-5);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isNull();
}
}
@Test
public void testLancePourScoreScoreTropGrand() {
try {
jetDe.getLancePourScore(7);
fail();
} catch (LanceDeException e) {
Assertions.assertThat(e.getCause()).isNull();
}
}
@Test
public void testLancePourScoreScore3() {
try {
List<IDe> esperes = Arrays.asList(D6.D6_RESULTAT_3, D6.D6_RESULTAT_4, D6.D6_RESULTAT_5, D6.D6_RESULTAT_6);
List<IDe> resultat = jetDe.getLancePourScore(3);
assertSimulation(esperes, resultat);
} catch (LanceDeException e) {
fail();
}
}
private void assertSimulation(List<IDe> esperes, List<IDe> resultats) {
Assertions.assertThat(resultats).hasSize(esperes.size());
Map<IDe, Integer> mapEsperes = getMapCount(esperes);
Map<IDe, Integer> mapResultats = getMapCount(resultats);
Assertions.assertThat(mapResultats).hasSize(mapEsperes.size());
for (Entry<IDe, Integer> entry : mapResultats.entrySet()) {
Assertions.assertThat(entry.getValue()).isNotNull();
Assertions.assertThat(mapEsperes.get(entry.getKey())).isNotNull();
Assertions.assertThat(entry.getValue()).isEqualTo(mapEsperes.get(entry.getKey()));
}
}
private Map<IDe, Integer> getMapCount(List<IDe> list) {
Map<IDe, Integer> map = new HashMap<>();
int nombre;
for (IDe de : list) {
nombre = (map.get(de) != null) ? map.get(de) : 0;
map.put(de, nombre + 1);
}
return map;
}
}
