Skip to contentMethod: createPlayerBuilder()
      1: package de.fhdw.gaming.ipspiel23.dilemma.domain.internals;
2: 
3: import java.util.ArrayList;
4: import java.util.HashMap;
5: import java.util.List;
6: import java.util.Map;
7: import java.util.stream.Collectors;
8: 
9: import de.fhdw.gaming.core.domain.DefaultObserverFactoryProvider;
10: import de.fhdw.gaming.core.domain.GameBuilder;
11: import de.fhdw.gaming.core.domain.GameException;
12: import de.fhdw.gaming.core.domain.ObserverFactoryProvider;
13: import de.fhdw.gaming.ipspiel23.dilemma.domain.IDilemmaGame;
14: import de.fhdw.gaming.ipspiel23.dilemma.domain.IDilemmaGameBuilder;
15: import de.fhdw.gaming.ipspiel23.dilemma.domain.IDilemmaPlayer;
16: import de.fhdw.gaming.ipspiel23.dilemma.domain.IDilemmaPlayerBuilder;
17: import de.fhdw.gaming.ipspiel23.dilemma.domain.IDilemmaStrategy;
18: import de.fhdw.gaming.ipspiel23.dilemma.moves.internals.DilemmaMove;
19: 
20: /**
21:  * Implements {@link IDilemmaGameBuilder}.
22:  */
23: public class DilemmaGameBuilder implements IDilemmaGameBuilder {
24:     
25:     /**
26:      * The {@link ObserverFactoryProvider}.
27:      */
28:     private ObserverFactoryProvider observerFactoryProvider;
29: 
30:     /**
31:      * The players participating in this game.
32:      */
33:     private final List<IDilemmaPlayer> players;
34: 
35:      /**
36:      * The player builders used to create the players. 
37:      * (player name -> builder)
38:      */
39:     private final Map<String, DilemmaPlayerBuilder> playerBuilders;
40: 
41:     /**
42:      * The maximum computation time per move in seconds.
43:      */
44:     private int maxComputationTimePerMove;
45: 
46:     /**
47:      * Creates a Dilemma game builder.
48:      */
49:     public DilemmaGameBuilder() {
50:         this.players = new ArrayList<>(2);
51:         this.playerBuilders = new HashMap<>();
52:         this.observerFactoryProvider = new DefaultObserverFactoryProvider();
53:         this.maxComputationTimePerMove = GameBuilder.DEFAULT_MAX_COMPUTATION_TIME_PER_MOVE;
54:     }
55: 
56:     @Override
57:     public IDilemmaPlayerBuilder createPlayerBuilder() {
58:         return new DilemmaPlayerBuilder(this);
59:     }
60: 
61:     /**
62:      * Called by {@link DilemmaPlayerBuilder} when a player is built. 
63:      * Required for strategy injection.
64:      * @param builder The builder that built the player.
65:      * @param player The player that was built.
66:      */
67:     void onPlayerBuilt(final DilemmaPlayerBuilder builder, final IDilemmaPlayer player) {
68:         this.playerBuilders.put(player.getName(), builder);
69:     }
70: 
71:     @Override
72:     public IDilemmaGameBuilder addPlayer(final IDilemmaPlayer player, final IDilemmaStrategy strategy)
73:             throws GameException {
74:         
75:         if (this.players.size() >= 2) {
76:             throw new GameException(String.format("More than two players are not allowed."));
77:         }
78:         final DilemmaPlayerBuilder builder = playerBuilders.getOrDefault(player.getName(), null);
79:         if (builder == null) {
80:             throw new GameException("Attempted to add player that was not built using a " 
81:                 + DilemmaPlayerBuilder.class.getSimpleName());
82:         }
83:         // we need a way to store the strategy in the player instance (because that's where it belongs)
84:         // that is handled via an internal callback set in the ctor of the player.
85:         // We don't want client code to be able to modify strategies, so no simple public setters :)
86:         builder.injectPlayerStrategyUsingHook(player, strategy);
87:         players.add(player);
88:         return this;
89:     }
90: 
91:     @Override
92:     public IDilemmaGameBuilder changeMaximumComputationTimePerMove(final int newMaxComputationTimePerMove) {
93:         this.maxComputationTimePerMove = newMaxComputationTimePerMove;
94:         return this;
95:     }
96: 
97:     @Override
98:     public IDilemmaGameBuilder changeObserverFactoryProvider(final ObserverFactoryProvider newObserverFactoryProvider) {
99:         this.observerFactoryProvider = newObserverFactoryProvider;
100:         return this;
101:     }
102: 
103:     /**
104:      * Builds the game with the predefined parameters.
105:      */
106:     @Override
107:     public IDilemmaGame build(final int id) throws GameException, InterruptedException {
108:         if (this.players.size() != 2) {
109:             throw new GameException("A Dilemma game needs exactly two players.");
110:         }
111: 
112:         final DilemmaState initialState = new DilemmaState(this.players.get(0), this.players.get(1));
113:         final Map<String, IDilemmaStrategy> strategies = this.players
114:             .stream()
115:             .collect(Collectors.toMap(p -> p.getName(), p -> p.getStrategy()));
116: 
117:         return new DilemmaGame(
118:             id,
119:             initialState,
120:             strategies,
121:             this.maxComputationTimePerMove,
122:             DilemmaMove.class::isInstance,
123:             this.observerFactoryProvider);
124:     }
125: }