Skip to content

Method: getMinimumNumberOfPlayers()

1:
2: package de.fhdw.gaming.ipspiel24.fg.domain.impl;
3:
4: import java.util.ArrayList;
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.ipspiel24.fg.domain.FGActivity;
23: import de.fhdw.gaming.ipspiel24.fg.domain.FGGameBuilder;
24: import de.fhdw.gaming.ipspiel24.fg.domain.FGGameBuilderFactory;
25: import de.fhdw.gaming.ipspiel24.fg.domain.FGPlayer;
26: import de.fhdw.gaming.ipspiel24.fg.domain.FGPlayerBuilder;
27: import de.fhdw.gaming.ipspiel24.fg.domain.FGStrategy;
28: import de.fhdw.gaming.ipspiel24.fg.domain.factory.FGDefaultStrategyFactoryProvider;
29: import de.fhdw.gaming.ipspiel24.fg.domain.factory.FGStrategyFactory;
30: import de.fhdw.gaming.ipspiel24.fg.domain.factory.FGStrategyFactoryProvider;
31: import de.fhdw.gaming.ipspiel24.fg.moves.factory.FGMoveFactory;
32: import de.fhdw.gaming.ipspiel24.fg.moves.impl.FGDefaultMoveFactory;
33:
34: /**
35: * Implements {@link GameBuilderFactory} by creating a FG game builder.
36: */
37: public final class FGGameBuilderFactoryImpl implements FGGameBuilderFactory {
38:
39: /**
40: * The number of players.
41: */
42: private static final int NUMBER_OF_PLAYERS = 2;
43: /**
44: * Smallest allowed maximum computation time per move in seconds.
45: */
46: private static final int MIN_MAX_COMPUTATION_TIME_PER_MOVE = 1;
47: /**
48: * Largest allowed maximum computation time per move in seconds.
49: */
50: private static final int MAX_MAX_COMPUTATION_TIME_PER_MOVE = 3600;
51:
52: /**
53: * All available FG strategies.
54: */
55: private final Set<FGStrategy> strategies;
56:
57: /**
58: * Creates a FG game factory. FG strategies are loaded by using the {@link java.util.ServiceLoader}.
59: * <p>
60: * This constructor is meant to be used by the {@link java.util.ServiceLoader}.
61: */
62: public FGGameBuilderFactoryImpl() {
63: this(new FGDefaultStrategyFactoryProvider());
64: }
65:
66: /**
67: * Creates a FG game factory.
68: *
69: * @param strategyFactoryProvider The {@link FGStrategyFactoryProvider} for loading FG strategies.
70: */
71: FGGameBuilderFactoryImpl(final FGStrategyFactoryProvider strategyFactoryProvider) {
72: final FGMoveFactory moveFactory = new FGDefaultMoveFactory();
73:
74: final List<FGStrategyFactory> factories = strategyFactoryProvider.getStrategyFactories();
75: this.strategies = new LinkedHashSet<>();
76: for (final FGStrategyFactory factory : factories) {
77: this.strategies.add(factory.create(moveFactory));
78: }
79: }
80:
81: @Override
82: public String getName() {
83: return "FG";
84: }
85:
86: @Override
87: public int getMinimumNumberOfPlayers() {
88: return FGGameBuilderFactoryImpl.NUMBER_OF_PLAYERS;
89: }
90:
91: @Override
92: public int getMaximumNumberOfPlayers() {
93: return FGGameBuilderFactoryImpl.NUMBER_OF_PLAYERS;
94: }
95:
96: @Override
97: public List<? extends Strategy<?, ?, ?>> getStrategies() {
98: return new ArrayList<>(this.strategies);
99: }
100:
101: @Override
102: public FGGameBuilder createGameBuilder(final InputProvider inputProvider) throws GameException {
103: try {
104: final FGGameBuilder gameBuilder = new FGGameBuilderImpl();
105:
106: @SuppressWarnings("unchecked")
107: final Map<String,
108: Object> gameData = inputProvider.needInteger(
109: GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE,
110: "Maximum computation time per move in seconds",
111: Optional.of(GameBuilder.DEFAULT_MAX_COMPUTATION_TIME_PER_MOVE),
112: new MinValueValidator<>(FGGameBuilderFactoryImpl.MIN_MAX_COMPUTATION_TIME_PER_MOVE),
113: new MaxValueValidator<>(FGGameBuilderFactoryImpl.MAX_MAX_COMPUTATION_TIME_PER_MOVE))
114: .requestData("Game properties");
115:
116: gameBuilder.changeMaximumComputationTimePerMove(
117: (Integer) gameData.get(GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE));
118:
119: final InputProvider firstPlayerInputProvider = inputProvider.getNext(gameData);
120: final Map<String, Object> firstPlayerData = this.requestPlayerData(firstPlayerInputProvider,
121: "Player 1", true);
122: final FGPlayer firstPlayer = this.createPlayer(gameBuilder.createPlayerBuilder(), firstPlayerData);
123: final FGStrategy firstPlayerStrategy = this.getStrategy(firstPlayerData);
124: gameBuilder.addPlayer(firstPlayer, firstPlayerStrategy);
125:
126: final InputProvider secondPlayerInputProvider = firstPlayerInputProvider.getNext(firstPlayerData);
127: final Map<String, Object> secondPlayerData = this.requestPlayerData(secondPlayerInputProvider,
128: "Player 2", false);
129: final FGPlayer secondPlayer = this.createPlayer(gameBuilder.createPlayerBuilder(), secondPlayerData);
130: final FGStrategy secondPlayerStrategy = this.getStrategy(secondPlayerData);
131: gameBuilder.addPlayer(secondPlayer, secondPlayerStrategy);
132:
133: return gameBuilder;
134: } catch (final InputProviderException e) {
135: throw new GameException(String.format("Creating FG game was aborted: %s", e.getMessage()), e);
136: }
137: }
138:
139: /**
140: * Returns data for a player builder.
141: *
142: * @param inputProvider The input provider.
143: * @param title The title for the UI.
144: * @param isFirstPlayer Differentiate between Player 1 and 2 payout
145: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
146: * dialog).
147: */
148: @SuppressWarnings("unchecked")
149: private Map<String, Object> requestPlayerData(final InputProvider inputProvider,
150: final String title, final boolean isFirstPlayer)
151: throws GameException, InputProviderException {
152: inputProvider
153: .needString(
154: GameBuilderFactory.PARAM_PLAYER_NAME,
155: isFirstPlayer ? "Klaus" : "Gabi",
156: Optional.empty(),
157: new PatternValidator(Pattern.compile("\\S+(\\s+\\S+)*")))
158: .needInteger(
159: FGGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_FOOTBALL_FOOTBALL,
160: "Player's outcome on Football/Football",
161: isFirstPlayer ? Optional.of(2) : Optional.of(1))
162: .needInteger(
163: FGGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_FOOTBALL_CINEMA,
164: "Player's outcome on Football/Cinema",
165: Optional.of(0))
166: .needInteger(
167: FGGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_CINEMA_FOOTBALL,
168: "Player's outcome on Cinema/Football",
169: Optional.of(0))
170: .needInteger(
171: FGGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_CINEMA_CINEMA,
172: "Player's outcome on Cinema/Cinema",
173: isFirstPlayer ? Optional.of(1) : Optional.of(2))
174: .needObject(GameBuilderFactory.PARAM_PLAYER_STRATEGY, "Strategy", Optional.empty(), this.strategies);
175:
176:
177:
178: return inputProvider.requestData(title);
179: }
180:
181: /**
182: * Creates a FG player.
183: *
184: * @param playerBuilder The player builder.
185: * @param playerData The requested player data.
186: * @return The created {@link FGPlayer}.
187: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
188: * dialog).
189: */
190: private FGPlayer createPlayer(final FGPlayerBuilder playerBuilder,
191: final Map<String, Object> playerData) throws GameException, InputProviderException {
192:
193: final Map<FGActivity, Map<FGActivity, Double>> possibleOutcomes = new LinkedHashMap<>();
194:
195: final Map<FGActivity, Double> possibleOutcomesNo = new LinkedHashMap<>();
196: possibleOutcomesNo.put(
197: FGActivity.FOOTBALL,
198: (double) (Integer) playerData.get(FGGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_FOOTBALL_FOOTBALL));
199: possibleOutcomesNo.put(
200: FGActivity.CINEMA,
201: (double) (Integer) playerData.get(FGGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_FOOTBALL_CINEMA));
202: possibleOutcomes.put(FGActivity.FOOTBALL, possibleOutcomesNo);
203:
204: final Map<FGActivity, Double> possibleOutcomesYes = new LinkedHashMap<>();
205: possibleOutcomesYes.put(
206: FGActivity.FOOTBALL,
207: (double) (Integer) playerData.get(FGGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_CINEMA_FOOTBALL));
208: possibleOutcomesYes.put(
209: FGActivity.CINEMA,
210: (double) (Integer) playerData.get(FGGameBuilderFactory.PARAM_PLAYER_OUTCOME_ON_CINEMA_CINEMA));
211: possibleOutcomes.put(FGActivity.CINEMA, possibleOutcomesYes);
212:
213: return playerBuilder.changeName((String) playerData.get(GameBuilderFactory.PARAM_PLAYER_NAME))
214: .changePossibleOutcomes(possibleOutcomes).build();
215: }
216:
217: /**
218: * Returns a FG strategy.
219: *
220: * @param playerData The requested player data.
221: * @return The FG strategy.
222: */
223: private FGStrategy getStrategy(final Map<String, Object> playerData) {
224: return (FGStrategy) playerData.get(GameBuilderFactory.PARAM_PLAYER_STRATEGY);
225: }
226: }