Skip to content

Method: SSPGameBuilderFactoryImpl()

1: package de.schereSteinPapier.domain.impl;
2:
3: import static de.schereSteinPapier.SSPConstants.AuswahlConstants.PAPIER;
4: import static de.schereSteinPapier.SSPConstants.AuswahlConstants.SCHERE;
5: import static de.schereSteinPapier.SSPConstants.AuswahlConstants.STEIN;
6:
7: import java.util.ArrayList;
8: import java.util.LinkedHashMap;
9: import java.util.LinkedHashSet;
10: import java.util.List;
11: import java.util.Map;
12: import java.util.Optional;
13: import java.util.Set;
14: import java.util.regex.Pattern;
15:
16: import de.fhdw.gaming.core.domain.GameBuilder;
17: import de.fhdw.gaming.core.domain.GameBuilderFactory;
18: import de.fhdw.gaming.core.domain.GameException;
19: import de.fhdw.gaming.core.domain.Strategy;
20: import de.fhdw.gaming.core.ui.InputProvider;
21: import de.fhdw.gaming.core.ui.InputProviderException;
22: import de.fhdw.gaming.core.ui.type.validator.MaxValueValidator;
23: import de.fhdw.gaming.core.ui.type.validator.MinValueValidator;
24: import de.fhdw.gaming.core.ui.type.validator.PatternValidator;
25: import de.schereSteinPapier.domain.SSPGameBuilder;
26: import de.schereSteinPapier.domain.SSPGameBuilderFactory;
27: import de.schereSteinPapier.domain.SSPPlayer;
28: import de.schereSteinPapier.domain.SSPPlayerBuilder;
29: import de.schereSteinPapier.domain.SSPStrategy;
30: import de.schereSteinPapier.domain.factory.SSPDefaultStrategyFactoryProvider;
31: import de.schereSteinPapier.domain.factory.SSPStrategyFactory;
32: import de.schereSteinPapier.domain.factory.SSPStrategyFactoryProvider;
33: import de.schereSteinPapier.moves.factory.SSPMoveFactory;
34: import de.schereSteinPapier.moves.impl.SSPDefaultMoveFactory;
35:
36: /**
37: * Implements {@link SSPGameBuilderFactory} by creating a SSP game builder.
38: */
39: public final class SSPGameBuilderFactoryImpl implements SSPGameBuilderFactory {
40:
41: /**
42: * The number of players.
43: */
44: private static final int NUMBER_OF_PLAYERS = 2;
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: * Largest allowed maximum computation time per move in seconds.
51: */
52: private static final int MAX_MAX_COMPUTATION_TIME_PER_MOVE = 3600;
53:
54: /**
55: * All available SSP strategies.
56: */
57: private final Set<SSPStrategy> strategies;
58:
59: /**
60: * Creates a SSP game factory. SSP strategies are loaded by using the {@link java.util.ServiceLoader}.
61: * <p>
62: * This constructor is meant to be used by the {@link java.util.ServiceLoader}.
63: */
64: public SSPGameBuilderFactoryImpl() {
65: this(new SSPDefaultStrategyFactoryProvider());
66: }
67:
68: /**
69: * Creates a SSP game factory.
70: *
71: * @param strategyFactoryProvider The {@link SSPStrategyFactoryProvider} for loading SSP strategies.
72: */
73: SSPGameBuilderFactoryImpl(final SSPStrategyFactoryProvider strategyFactoryProvider) {
74: final SSPMoveFactory moveFactory = new SSPDefaultMoveFactory();
75:
76: final List<SSPStrategyFactory> factories = strategyFactoryProvider.getStrategyFactories();
77: this.strategies = new LinkedHashSet<>();
78: for (final SSPStrategyFactory factory : factories) {
79: this.strategies.add(factory.create(moveFactory));
80: }
81: }
82:
83: @Override
84: public String getName() {
85: return "SSP";
86: }
87:
88: @Override
89: public int getMinimumNumberOfPlayers() {
90: return SSPGameBuilderFactoryImpl.NUMBER_OF_PLAYERS;
91: }
92:
93: @Override
94: public int getMaximumNumberOfPlayers() {
95: return SSPGameBuilderFactoryImpl.NUMBER_OF_PLAYERS;
96: }
97:
98: @Override
99: public List<? extends Strategy<?, ?, ?>> getStrategies() {
100: return new ArrayList<>(this.strategies);
101: }
102:
103: @Override
104: public SSPGameBuilder createGameBuilder(final InputProvider inputProvider) throws GameException {
105: try {
106: final SSPGameBuilder gameBuilder = new SSPGameBuilderImpl();
107:
108: @SuppressWarnings("unchecked")
109: final Map<String,
110: Object> gameData = inputProvider.needInteger(
111: GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE,
112: "Maximum computation time per move in seconds",
113: Optional.of(GameBuilder.DEFAULT_MAX_COMPUTATION_TIME_PER_MOVE),
114: new MinValueValidator<>(SSPGameBuilderFactoryImpl.MIN_MAX_COMPUTATION_TIME_PER_MOVE),
115: new MaxValueValidator<>(SSPGameBuilderFactoryImpl.MAX_MAX_COMPUTATION_TIME_PER_MOVE))
116: .requestData("Game properties");
117:
118: gameBuilder.changeMaximumComputationTimePerMove(
119: (Integer) gameData.get(GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE));
120:
121: final InputProvider firstPlayerInputProvider = inputProvider.getNext(gameData);
122: final Map<String, Object> firstPlayerData = this.requestPlayerData(firstPlayerInputProvider, "Player 1");
123: final SSPPlayer firstPlayer = this
124: .createPlayer(gameBuilder.createPlayerBuilder(), firstPlayerData);
125: final SSPStrategy firstPlayerStrategy = this.getStrategy(firstPlayerData);
126: gameBuilder.addPlayer(firstPlayer, firstPlayerStrategy);
127:
128: final InputProvider secondPlayerInputProvider = firstPlayerInputProvider.getNext(firstPlayerData);
129: final Map<String, Object> secondPlayerData = this.requestPlayerData(secondPlayerInputProvider, "Player 2");
130: final SSPPlayer secondPlayer = this
131: .createPlayer(gameBuilder.createPlayerBuilder(), secondPlayerData);
132: final SSPStrategy secondPlayerStrategy = this.getStrategy(secondPlayerData);
133: gameBuilder.addPlayer(secondPlayer, secondPlayerStrategy);
134:
135: return gameBuilder;
136: } catch (final InputProviderException e) {
137: throw new GameException(String.format("Creating Demo game was aborted: %s", e.getMessage()), e);
138: }
139: }
140:
141: /**
142: * Returns data for a player builder.
143: *
144: * @param inputProvider The input provider.
145: * @param title The title for the UI.
146: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
147: * dialog).
148: */
149: @SuppressWarnings("unchecked")
150: private Map<String, Object> requestPlayerData(final InputProvider inputProvider, final String title)
151: throws GameException, InputProviderException {
152: if (title.equals("Player 1")) {
153: inputProvider
154: .needString(
155: GameBuilderFactory.PARAM_PLAYER_NAME,
156: "Name",
157: Optional.empty(),
158: new PatternValidator(Pattern.compile("\\S+(\\s+\\S+)*")))
159: .needInteger(
160: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_SCHERE_SCHERE,
161: "Player's outcome on Schere/Schere",
162: Optional.of(0))
163: .needInteger(
164: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_SCHERE_STEIN,
165: "Player's outcome on Schere/Stein",
166: Optional.of(-1))
167: .needInteger(
168: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_SCHERE_PAPIER,
169: "Player's outcome on Schere/Papier",
170: Optional.of(1))
171: .needInteger(
172: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_STEIN_SCHERE,
173: "Player's outcome on Stein/Schere",
174: Optional.of(1))
175: .needInteger(
176: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_STEIN_STEIN,
177: "Player's outcome on Stein/Stein",
178: Optional.of(0))
179: .needInteger(
180: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_STEIN_PAPIER,
181: "Player's outcome on Stein/Papier",
182: Optional.of(-1))
183: .needInteger(
184: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_PAPIER_SCHERE,
185: "Player's outcome on Papier/Schere",
186: Optional.of(-1))
187: .needInteger(
188: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_PAPIER_STEIN,
189: "Player's outcome on Papier/Stein",
190: Optional.of(1))
191: .needInteger(
192: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_PAPIER_PAPIER,
193: "Player's outcome on Papier/Papier",
194: Optional.of(0))
195: .needObject(GameBuilderFactory.PARAM_PLAYER_STRATEGY, "Strategy",
196: Optional.empty(), this.strategies);
197: } else {
198: inputProvider
199: .needString(
200: GameBuilderFactory.PARAM_PLAYER_NAME,
201: "Name",
202: Optional.empty(),
203: new PatternValidator(Pattern.compile("\\S+(\\s+\\S+)*")))
204: .needInteger(
205: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_SCHERE_SCHERE,
206: "Player's outcome on Schere/Schere",
207: Optional.of(0))
208: .needInteger(
209: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_SCHERE_STEIN,
210: "Player's outcome on Schere/Stein",
211: Optional.of(1))
212: .needInteger(
213: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_SCHERE_PAPIER,
214: "Player's outcome on Schere/Papier",
215: Optional.of(-1))
216: .needInteger(
217: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_STEIN_SCHERE,
218: "Player's outcome on Stein/Schere",
219: Optional.of(-1))
220: .needInteger(
221: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_STEIN_STEIN,
222: "Player's outcome on Stein/Stein",
223: Optional.of(0))
224: .needInteger(
225: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_STEIN_PAPIER,
226: "Player's outcome on Stein/Papier",
227: Optional.of(1))
228: .needInteger(
229: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_PAPIER_SCHERE,
230: "Player's outcome on Papier/Schere",
231: Optional.of(1))
232: .needInteger(
233: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_PAPIER_STEIN,
234: "Player's outcome on Papier/Stein",
235: Optional.of(-1))
236: .needInteger(
237: SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_PAPIER_PAPIER,
238: "Player's outcome on Papier/Papier",
239: Optional.of(0))
240: .needObject(GameBuilderFactory.PARAM_PLAYER_STRATEGY, "Strategy",
241: Optional.empty(), this.strategies);
242: }
243: return inputProvider.requestData(title);
244: }
245:
246: /**
247: * Creates a SSP player.
248: *
249: * @param playerBuilder The player builder.
250: * @param playerData The requested player data.
251: * @return The created {@link SSPPlayer}.
252: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
253: * dialog).
254: */
255: private SSPPlayer createPlayer(final SSPPlayerBuilder playerBuilder,
256: final Map<String, Object> playerData) throws GameException, InputProviderException {
257:
258: final Map<String, Map<String, Double>> possibleOutcomes = new LinkedHashMap<>();
259:
260: final Map<String, Double> possibleOutcomesSchere = new LinkedHashMap<>();
261: possibleOutcomesSchere.put(
262: SCHERE,
263: (double) (Integer) playerData.get(SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_SCHERE_SCHERE));
264: possibleOutcomesSchere.put(
265: STEIN,
266: (double) (Integer) playerData.get(SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_SCHERE_STEIN));
267: possibleOutcomesSchere.put(
268: PAPIER,
269: (double) (Integer) playerData.get(SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_SCHERE_PAPIER));
270: possibleOutcomes.put(SCHERE, possibleOutcomesSchere);
271:
272: final Map<String, Double> possibleOutcomesStein = new LinkedHashMap<>();
273: possibleOutcomesStein.put(
274: SCHERE,
275: (double) (Integer) playerData.get(SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_STEIN_SCHERE));
276: possibleOutcomesStein.put(
277: STEIN,
278: (double) (Integer) playerData.get(SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_STEIN_STEIN));
279: possibleOutcomesStein.put(
280: PAPIER,
281: (double) (Integer) playerData.get(SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_STEIN_PAPIER));
282: possibleOutcomes.put(STEIN, possibleOutcomesStein);
283:
284: final Map<String, Double> possibleOutcomesPapier = new LinkedHashMap<>();
285: possibleOutcomesPapier.put(
286: SCHERE,
287: (double) (Integer) playerData.get(SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_PAPIER_SCHERE));
288: possibleOutcomesPapier.put(
289: STEIN,
290: (double) (Integer) playerData.get(SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_PAPIER_STEIN));
291: possibleOutcomesPapier.put(
292: PAPIER,
293: (double) (Integer) playerData.get(SSPGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_PAPIER_PAPIER));
294: possibleOutcomes.put(PAPIER, possibleOutcomesPapier);
295:
296: return playerBuilder.changeName((String) playerData.get(GameBuilderFactory.PARAM_PLAYER_NAME))
297: .changePossibleOutcomes(possibleOutcomes).build();
298: }
299:
300: /**
301: * Returns a SSP strategy.
302: *
303: * @param playerData The requested player data.
304: * @return The SSP strategy.
305: */
306: private SSPStrategy getStrategy(final Map<String, Object> playerData) {
307: return (SSPStrategy) playerData.get(GameBuilderFactory.PARAM_PLAYER_STRATEGY);
308: }
309: }