Skip to content

Method: createGameBuilder(InputProvider)

1: package de.fhdw.gaming.ipspiel23.ht.domain.impl;
2:
3: import java.util.ArrayList;
4: import java.util.HashSet;
5: import java.util.LinkedHashMap;
6: import java.util.LinkedHashSet;
7: import java.util.List;
8: import java.util.Map;
9: import java.util.Optional;
10: import java.util.Set;
11: import java.util.regex.Pattern;
12:
13: import de.fhdw.gaming.core.domain.GameBuilder;
14: import de.fhdw.gaming.core.domain.GameBuilderFactory;
15: import de.fhdw.gaming.core.domain.GameException;
16: import de.fhdw.gaming.core.domain.Strategy;
17: import de.fhdw.gaming.core.ui.InputProvider;
18: import de.fhdw.gaming.core.ui.InputProviderException;
19: import de.fhdw.gaming.core.ui.type.validator.MaxValueValidator;
20: import de.fhdw.gaming.core.ui.type.validator.MinValueValidator;
21: import de.fhdw.gaming.core.ui.type.validator.PatternValidator;
22: import de.fhdw.gaming.core.ui.type.validator.ValueSetValidator;
23: import de.fhdw.gaming.ipspiel23.ht.domain.Answer;
24: import de.fhdw.gaming.ipspiel23.ht.domain.IHTGameBuilder;
25: import de.fhdw.gaming.ipspiel23.ht.domain.IHTGameBuilderFactory;
26: import de.fhdw.gaming.ipspiel23.ht.domain.IHTPlayer;
27: import de.fhdw.gaming.ipspiel23.ht.domain.IHTPlayerBuilder;
28: import de.fhdw.gaming.ipspiel23.ht.moves.factory.HTDefaultMoveFactory;
29: import de.fhdw.gaming.ipspiel23.ht.moves.factory.IHTMoveFactory;
30: import de.fhdw.gaming.ipspiel23.ht.strategy.IHTStrategy;
31: import de.fhdw.gaming.ipspiel23.ht.strategy.IHTStrategyFactory;
32: import de.fhdw.gaming.ipspiel23.ht.strategy.factory.HTDefaultStrategyFactoryProvider;
33: import de.fhdw.gaming.ipspiel23.ht.strategy.factory.IHTStrategyFactoryProvider;
34:
35: /**
36: * Represents a factory for game builder instances.
37: */
38: public final class HTGameBuilderFactory implements IHTGameBuilderFactory {
39:
40: /**
41: * The number of players.
42: */
43: private static final int NUMBER_OF_PLAYERS = 2;
44:
45: /**
46: * Smallest allowed maximum computation time per move in seconds.
47: */
48: private static final int MIN_MAX_COMPUTATION_TIME_PER_MOVE = 1;
49:
50: /**
51: * Largest allowed maximum computation time per move in seconds.
52: */
53: private static final int MAX_MAX_COMPUTATION_TIME_PER_MOVE = 3600;
54:
55: /**
56: * The available strategies.
57: */
58: private final Set<IHTStrategy> strategies;
59:
60: /**
61: * Creates a new instance of {@link HTGameBuilderFactory}.
62: */
63: public HTGameBuilderFactory() {
64: this(new HTDefaultStrategyFactoryProvider());
65: }
66:
67: /**
68: * Creates a new instance of {@link HTGameBuilderFactory}.
69: *
70: * @param provider The provider for the strategy factories.
71: */
72: public HTGameBuilderFactory(final IHTStrategyFactoryProvider provider) {
73: final IHTMoveFactory moveFactory = new HTDefaultMoveFactory();
74:
75: final List<IHTStrategyFactory> factories = provider.getStrategyFactories();
76: this.strategies = new LinkedHashSet<>();
77: for (final IHTStrategyFactory factory : factories) {
78: this.strategies.add(factory.create(moveFactory));
79: }
80: }
81:
82: @Override
83: public String getName() {
84: return "Heads or Tails";
85: }
86:
87: @Override
88: public int getMinimumNumberOfPlayers() {
89: return NUMBER_OF_PLAYERS;
90: }
91:
92: @Override
93: public int getMaximumNumberOfPlayers() {
94: return NUMBER_OF_PLAYERS;
95: }
96:
97: @Override
98: public List<? extends Strategy<?, ?, ?>> getStrategies() {
99: return new ArrayList<>(this.strategies);
100: }
101:
102: @Override
103: public IHTGameBuilder createGameBuilder(final InputProvider inputProvider) throws GameException {
104: try {
105: final IHTGameBuilder gameBuilder = new HTGameBuilder();
106:
107: @SuppressWarnings("unchecked")
108: final Map<String,
109: Object> gameData = inputProvider.needInteger(
110: GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE,
111: "Maximum computation time per move in seconds",
112: Optional.of(GameBuilder.DEFAULT_MAX_COMPUTATION_TIME_PER_MOVE),
113: new MinValueValidator<>(HTGameBuilderFactory.MIN_MAX_COMPUTATION_TIME_PER_MOVE),
114: new MaxValueValidator<>(HTGameBuilderFactory.MAX_MAX_COMPUTATION_TIME_PER_MOVE))
115: .requestData("Game properties");
116:
117: gameBuilder.changeMaximumComputationTimePerMove(
118: (Integer) gameData.get(GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE));
119:
120: final InputProvider playerInputProvider1 = inputProvider.getNext(gameData);
121: final Map<String, Object> playerData1 = this.requestPlayerData(playerInputProvider1, "Player 1", 1);
122: final IHTPlayer player1 = this.createPlayer(gameBuilder.createPlayerBuilder(), playerData1);
123: final IHTStrategy playerStrategy1 = this.getStrategy(playerData1);
124: gameBuilder.addPlayer(player1, playerStrategy1);
125:
126: final InputProvider playerInputProvider2 = playerInputProvider1.getNext(playerData1);
127: final Map<String, Object> playerData2 = this.requestPlayerData(playerInputProvider2, "Player 2", -1);
128: final IHTPlayer player2 = this.createPlayer(gameBuilder.createPlayerBuilder(), playerData2);
129: final IHTStrategy playerStrategy2 = this.getStrategy(playerData2);
130: gameBuilder.addPlayer(player2, playerStrategy2);
131:
132:• if (player1.getPossibleOutcomes().equals(player2.getPossibleOutcomes())) {
133: throw new GameException("Players cannot bet on the same outcome!");
134: }
135:
136: return gameBuilder;
137: } catch (final InputProviderException e) {
138: throw new GameException(String.format("Creating HT game was aborted: %s", e.getMessage()), e);
139: }
140: }
141:
142: /**
143: * Returns data for a player builder.
144: *
145: * @param inputProvider The input provider.
146: * @param title The title for the UI.
147: * @param defaultValueFactor The factor to be multiplied with the outcomes (allows easily inverting outcomes
148: * /pre-filling input provider stuff)
149: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
150: * dialog).
151: */
152: @SuppressWarnings("unchecked")
153: private Map<String, Object> requestPlayerData(final InputProvider inputProvider, final String title,
154: final int defaultValueFactor)
155: throws GameException, InputProviderException {
156: final Set<Integer> allowedOutcomeValues = new HashSet<>();
157: allowedOutcomeValues.add(1);
158: allowedOutcomeValues.add(-1);
159:
160: final ValueSetValidator<Integer> outcomeValidator = new ValueSetValidator<>(allowedOutcomeValues);
161:
162: inputProvider
163: .needString(
164: GameBuilderFactory.PARAM_PLAYER_NAME,
165: "Name",
166: Optional.empty(),
167: new PatternValidator(Pattern.compile("\\S+(\\s+\\S+)*")))
168: .needInteger(
169: PARAM_PLAYER_OUTCOME_EQUAL,
170: "Player's outcome on equal sides (HH/TT/EE)",
171: Optional.of(1 * defaultValueFactor),
172: outcomeValidator)
173: .needInteger(
174: PARAM_PLAYER_OUTCOME_DIFFERENT,
175: "Player's outcome on different sides (HT/HE/TH/TE/EH/ET)",
176: Optional.of(-1 * defaultValueFactor),
177: outcomeValidator)
178: .needObject(GameBuilderFactory.PARAM_PLAYER_STRATEGY, "Strategy", Optional.empty(), this.strategies);
179:
180: return inputProvider.requestData(title);
181: }
182:
183: /**
184: * Creates a HT player.
185: *
186: * @param playerBuilder The player builder.
187: * @param playerData The requested player data.
188: * @return The created {@link IHTPlayer}.
189: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
190: * dialog).
191: */
192: private IHTPlayer createPlayer(final IHTPlayerBuilder playerBuilder,
193: final Map<String, Object> playerData) throws GameException, InputProviderException {
194: final double equalOutcome = (double) (Integer) playerData.get(PARAM_PLAYER_OUTCOME_EQUAL);
195: final double differentOutcome = (double) (Integer) playerData.get(PARAM_PLAYER_OUTCOME_DIFFERENT);
196:
197: if (equalOutcome == differentOutcome) {
198: throw new GameException("Outcomes for equal and different sides must not be identical.");
199: }
200:
201: final Map<Answer, Map<Answer, Double>> possibleOutcomes = new LinkedHashMap<>();
202:
203: final Map<Answer, Double> possibleOutcomesHeads = new LinkedHashMap<>();
204: possibleOutcomesHeads.put(Answer.HEADS, equalOutcome);
205: possibleOutcomesHeads.put(Answer.TAILS, differentOutcome);
206: possibleOutcomesHeads.put(Answer.EDGE, differentOutcome);
207: possibleOutcomes.put(Answer.HEADS, possibleOutcomesHeads);
208:
209: final Map<Answer, Double> possibleOutcomesTails = new LinkedHashMap<>();
210: possibleOutcomesTails.put(Answer.HEADS, differentOutcome);
211: possibleOutcomesTails.put(Answer.TAILS, equalOutcome);
212: possibleOutcomesTails.put(Answer.EDGE, differentOutcome);
213: possibleOutcomes.put(Answer.TAILS, possibleOutcomesTails);
214:
215: final Map<Answer, Double> possibleOutcomesEdge = new LinkedHashMap<>();
216: possibleOutcomesEdge.put(Answer.HEADS, differentOutcome);
217: possibleOutcomesEdge.put(Answer.TAILS, differentOutcome);
218: possibleOutcomesEdge.put(Answer.EDGE, equalOutcome);
219: possibleOutcomes.put(Answer.EDGE, possibleOutcomesEdge);
220:
221: return playerBuilder.changeName((String) playerData.get(GameBuilderFactory.PARAM_PLAYER_NAME))
222: .changePossibleOutcomes(possibleOutcomes).build();
223: }
224:
225: /**
226: * Returns a HT strategy.
227: *
228: * @param playerData The requested player data.
229: * @return The HT strategy.
230: */
231: private IHTStrategy getStrategy(final Map<String, Object> playerData) {
232: return (IHTStrategy) playerData.get(GameBuilderFactory.PARAM_PLAYER_STRATEGY);
233: }
234: }