Skip to content

Method: getMinimumNumberOfPlayers()

1: /*
2: * Copyright © 2021 Fachhochschule für die Wirtschaft (FHDW) Hannover
3: *
4: * This file is part of ipspiel21-viergewinnt-core.
5: *
6: * ipspiel21-viergewinnt-core is free software: you can redistribute it and/or modify it under
7: * the terms of the GNU General Public License as published by the Free Software
8: * Foundation, either version 3 of the License, or (at your option) any later
9: * version.
10: *
11: * ipspiel21-viergewinnt-core is distributed in the hope that it will be useful, but WITHOUT
12: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14: * details.
15: *
16: * You should have received a copy of the GNU General Public License along with
17: * ipspiel21-viergewinnt-core. If not, see <http://www.gnu.org/licenses/>.
18: */
19: package de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.impl;
20:
21: import java.util.ArrayList;
22: import java.util.LinkedHashSet;
23: import java.util.List;
24: import java.util.Map;
25: import java.util.Optional;
26: import java.util.Set;
27: import java.util.regex.Pattern;
28:
29: import de.fhdw.gaming.core.domain.GameBuilder;
30: import de.fhdw.gaming.core.domain.GameBuilderFactory;
31: import de.fhdw.gaming.core.domain.GameException;
32: import de.fhdw.gaming.core.domain.Strategy;
33: import de.fhdw.gaming.core.ui.InputProvider;
34: import de.fhdw.gaming.core.ui.InputProviderException;
35: import de.fhdw.gaming.core.ui.type.validator.MaxValueValidator;
36: import de.fhdw.gaming.core.ui.type.validator.MinValueValidator;
37: import de.fhdw.gaming.core.ui.type.validator.PatternValidator;
38: import de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.VierGewinntGameBuilder;
39: import de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.VierGewinntGameBuilderFactory;
40: import de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.VierGewinntPlayerBuilder;
41: import de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.VierGewinntStrategy;
42: import de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.factory.VierGewinntDefaultStrategyFactoryProvider;
43: import de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.factory.VierGewinntStrategyFactory;
44: import de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.factory.VierGewinntStrategyFactoryProvider;
45: import de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.moves.factory.VierGewinntDefaultMoveFactory;
46: import de.fhdw.gaming.ipspiel21.viergewinnt.core.domain.moves.factory.VierGewinntMoveFactory;
47:
48: /**
49: * Implements {@link VierGewinntGameBuilderFactory} by creating a Vier Gewinnt game builder.
50: */
51: public final class VierGewinntGameBuilderFactoryImpl implements VierGewinntGameBuilderFactory {
52:
53: /**
54: * The number of players.
55: */
56: private static final int NUMBER_OF_PLAYERS = 2;
57: /**
58: * Minimum number of rows of the board.
59: */
60: private static final int MIN_ROW_SIZE = 4;
61: /**
62: * Minimum number of columns of the board.
63: */
64: private static final int MIN_COLUMN_SIZE = 4;
65: /**
66: * Maximum number of rows of the board.
67: */
68: private static final int MAX_ROW_SIZE = 7;
69: /**
70: * Maximum number of rows of the board.
71: */
72: private static final int MAX_COLUMN_SIZE = 7;
73: /**
74: * Smallest allowed maximum computation time per move in seconds.
75: */
76: private static final int MIN_MAX_COMPUTATION_TIME_PER_MOVE = 1;
77: /**
78: * Largest allowed maximum computation time per move in seconds.
79: */
80: private static final int MAX_MAX_COMPUTATION_TIME_PER_MOVE = 3600;
81:
82: /**
83: * All available Vier Gewinnt strategies.
84: */
85: private final Set<VierGewinntStrategy> strategies;
86:
87: /**
88: * Creates an Vier Gewinnt game factory. Vier Gewinnt strategies are loaded by using the
89: * {@link java.util.ServiceLoader}.
90: * <p>
91: * This constructor is meant to be used by the {@link java.util.ServiceLoader}.
92: */
93: public VierGewinntGameBuilderFactoryImpl() {
94: this(new VierGewinntDefaultStrategyFactoryProvider());
95: }
96:
97: /**
98: * Creates an Vier Gewinnt game factory.
99: *
100: * @param strategyFactoryProvider The {@link VierGewinntStrategyFactoryProvider} for loading Vier Gewinnt
101: * strategies.
102: */
103: VierGewinntGameBuilderFactoryImpl(final VierGewinntStrategyFactoryProvider strategyFactoryProvider) {
104: final VierGewinntMoveFactory moveFactory = new VierGewinntDefaultMoveFactory();
105:
106: final List<VierGewinntStrategyFactory> factories = strategyFactoryProvider.getStrategyFactories();
107: this.strategies = new LinkedHashSet<>();
108: for (final VierGewinntStrategyFactory factory : factories) {
109: this.strategies.add(factory.create(moveFactory));
110: }
111: }
112:
113: @Override
114: public String getName() {
115: return "VierGewinnt";
116: }
117:
118: @Override
119: public int getMinimumNumberOfPlayers() {
120: return VierGewinntGameBuilderFactoryImpl.NUMBER_OF_PLAYERS;
121: }
122:
123: @Override
124: public int getMaximumNumberOfPlayers() {
125: return VierGewinntGameBuilderFactoryImpl.NUMBER_OF_PLAYERS;
126: }
127:
128: @Override
129: public List<? extends Strategy<?, ?, ?>> getStrategies() {
130: return new ArrayList<>(this.strategies);
131: }
132:
133: @Override
134: public VierGewinntGameBuilder createGameBuilder(final InputProvider inputProvider) throws GameException {
135: try {
136: final VierGewinntGameBuilder gameBuilder = new VierGewinntGameBuilderImpl();
137:
138: @SuppressWarnings("unchecked")
139: final Map<String, Object> gameData = inputProvider
140: .needInteger(VierGewinntGameBuilderFactory.PARAM_COLUMN_SIZE, "Number of columns",
141: Optional.of(VierGewinntGameBuilder.DEFAULT_COLUMN_SIZE),
142: new MinValueValidator<>(VierGewinntGameBuilderFactoryImpl.MIN_COLUMN_SIZE),
143: new MaxValueValidator<>(VierGewinntGameBuilderFactoryImpl.MAX_COLUMN_SIZE))
144: .needInteger(VierGewinntGameBuilderFactory.PARAM_ROW_SIZE, "Number of rows",
145: Optional.of(VierGewinntGameBuilder.DEFAULT_ROW_SIZE),
146: new MinValueValidator<>(VierGewinntGameBuilderFactoryImpl.MIN_ROW_SIZE),
147: new MaxValueValidator<>(VierGewinntGameBuilderFactoryImpl.MAX_ROW_SIZE))
148: .needInteger(GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE,
149: "Maximum computation time per move in seconds",
150: Optional.of(GameBuilder.DEFAULT_MAX_COMPUTATION_TIME_PER_MOVE),
151: new MinValueValidator<>(
152: VierGewinntGameBuilderFactoryImpl.MIN_MAX_COMPUTATION_TIME_PER_MOVE),
153: new MaxValueValidator<>(
154: VierGewinntGameBuilderFactoryImpl.MAX_MAX_COMPUTATION_TIME_PER_MOVE))
155: .requestData("Board properties");
156:
157: gameBuilder.changeColumnSize((Integer) gameData.get(VierGewinntGameBuilderFactory.PARAM_COLUMN_SIZE));
158: gameBuilder.changeRowSize((Integer) gameData.get(VierGewinntGameBuilderFactory.PARAM_ROW_SIZE));
159: gameBuilder.changeMaximumComputationTimePerMove(
160: (Integer) gameData.get(GameBuilderFactory.PARAM_MAX_COMPUTATION_TIME_PER_MOVE));
161:
162: final InputProvider firstPlayerInputProvider = inputProvider.getNext(gameData);
163: final Map<String, Object> firstPlayerData = this.requestPlayerData(firstPlayerInputProvider, "Player 1",
164: Optional.empty());
165: final VierGewinntPlayerBuilder firstPlayerBuilder = this
166: .initPlayerBuilder(gameBuilder.createPlayerBuilder(), firstPlayerData);
167: final VierGewinntStrategy firstPlayerStrategy = this.getStrategy(firstPlayerData);
168: gameBuilder.addPlayerBuilder(firstPlayerBuilder, firstPlayerStrategy);
169:
170: final InputProvider secondPlayerInputProvider = firstPlayerInputProvider.getNext(firstPlayerData);
171: final Map<String, Object> secondPlayerData = this.requestPlayerData(secondPlayerInputProvider, "Player 2",
172: Optional.of(
173: !(Boolean) firstPlayerData.get(VierGewinntGameBuilderFactory.PARAM_PLAYER_USING_YELLOW)));
174: final VierGewinntPlayerBuilder secondPlayerBuilder = this
175: .initPlayerBuilder(gameBuilder.createPlayerBuilder(), secondPlayerData);
176: final VierGewinntStrategy secondPlayerStrategy = this.getStrategy(secondPlayerData);
177: gameBuilder.addPlayerBuilder(secondPlayerBuilder, secondPlayerStrategy);
178:
179: return gameBuilder;
180: } catch (final InputProviderException e) {
181: throw new GameException(String.format("Creating Vier Gewinnt game was aborted: %s", e.getMessage()), e);
182: }
183: }
184:
185: /**
186: * Initialises an Vier Gewinnt player builder.
187: *
188: * @param inputProvider The input provider.
189: * @param title The title for the UI.
190: * @param usingYellow If set, determines whether the player uses yellow or red. Otherwise, the setting is
191: * initially set to crosses, and the user can change it at will.
192: * @return {@code playerBuilder}.
193: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
194: * dialog).
195: */
196: @SuppressWarnings("unchecked")
197: private Map<String, Object> requestPlayerData(final InputProvider inputProvider, final String title,
198: final Optional<Boolean> usingYellow) throws GameException, InputProviderException {
199:
200: inputProvider
201: .needString(GameBuilderFactory.PARAM_PLAYER_NAME, "Name", Optional.empty(),
202: new PatternValidator(Pattern.compile("\\S+(\\s+\\S+)*")))
203: .needBoolean(VierGewinntGameBuilderFactory.PARAM_PLAYER_USING_YELLOW, "Uses yellow",
204: Optional.of(Boolean.TRUE))
205: .needObject(GameBuilderFactory.PARAM_PLAYER_STRATEGY, "Strategy", Optional.empty(), this.strategies);
206:
207: if (usingYellow.isPresent()) {
208: inputProvider.fixedBoolean(VierGewinntGameBuilderFactory.PARAM_PLAYER_USING_YELLOW, usingYellow.get());
209: }
210:
211: return inputProvider.requestData(title);
212: }
213:
214: /**
215: * Initialises an Vier Gewinnt player builder.
216: *
217: * @param playerBuilder The player builder.
218: * @param playerData The requested player data.
219: * @return {@code playerBuilder}.
220: * @throws InputProviderException if the operation has been aborted prematurely (e.g. if the user cancelled a
221: * dialog).
222: */
223: private VierGewinntPlayerBuilder initPlayerBuilder(final VierGewinntPlayerBuilder playerBuilder,
224: final Map<String, Object> playerData) throws GameException, InputProviderException {
225:
226: return playerBuilder.changeName((String) playerData.get(GameBuilderFactory.PARAM_PLAYER_NAME))
227: .changeUsingYellow((Boolean) playerData.get(VierGewinntGameBuilderFactory.PARAM_PLAYER_USING_YELLOW));
228: }
229:
230: /**
231: * Returns an Vier Gewinnt strategy.
232: *
233: * @param playerData The requested player data.
234: * @return The Vier Gewinnt strategy.
235: */
236: private VierGewinntStrategy getStrategy(final Map<String, Object> playerData) {
237: return (VierGewinntStrategy) playerData.get(GameBuilderFactory.PARAM_PLAYER_STRATEGY);
238: }
239: }