package de.schereSteinPapier.domain.impl;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import de.fhdw.gaming.core.domain.DefaultObserverFactoryProvider;
import de.fhdw.gaming.core.domain.GameBuilder;
import de.fhdw.gaming.core.domain.GameException;
import de.fhdw.gaming.core.domain.ObserverFactoryProvider;
import de.schereSteinPapier.domain.SSPGame;
import de.schereSteinPapier.domain.SSPGameBuilder;
import de.schereSteinPapier.domain.SSPPlayer;
import de.schereSteinPapier.domain.SSPPlayerBuilder;
import de.schereSteinPapier.domain.SSPStrategy;
import de.schereSteinPapier.moves.impl.AbstractSSPMove;
/**
* Implements {@link SSPGameBuilder}.
*/
final class SSPGameBuilderImpl implements SSPGameBuilder {
/**
* The {@link ObserverFactoryProvider}.
*/
private ObserverFactoryProvider observerFactoryProvider;
/**
* The first player.
*/
private Optional<SSPPlayer> firstPlayer;
/**
* The strategy of the first player.
*/
private Optional<SSPStrategy> firstPlayerStrategy;
/**
* The second player.
*/
private Optional<SSPPlayer> secondPlayer;
/**
* The strategy of the second player.
*/
private Optional<SSPStrategy> secondPlayerStrategy;
/**
* The maximum computation time per move in seconds. Inherited from SSPGameBuilder which internally
* inherits it from gaming.core.
*/
private int maxComputationTimePerMove;
/**
* Creates a SSP game builder.
*/
SSPGameBuilderImpl() {
this.observerFactoryProvider = new DefaultObserverFactoryProvider();
this.firstPlayer = Optional.empty();
this.firstPlayerStrategy = Optional.empty();
this.secondPlayer = Optional.empty();
this.secondPlayerStrategy = Optional.empty();
this.maxComputationTimePerMove = GameBuilder.DEFAULT_MAX_COMPUTATION_TIME_PER_MOVE;
}
@Override
public SSPPlayerBuilder createPlayerBuilder() {
return new SSPPlayerBuilderImpl();
}
@Override
public SSPGameBuilder addPlayer(final SSPPlayer player, final SSPStrategy strategy)
throws GameException {
Objects.requireNonNull(player);
if (this.firstPlayer.isEmpty()) {
this.firstPlayer = Optional.of(player);
this.firstPlayerStrategy = Optional.of(Objects.requireNonNull(strategy, "firstPlayerStrategy"));
} else if (this.secondPlayer.isEmpty()) {
this.secondPlayer = Optional.of(player);
this.secondPlayerStrategy = Optional.of(Objects.requireNonNull(strategy, "secondPlayerStrategy"));
} else {
throw new GameException(String.format("More than two players are now allowed."));
}
return this;
}
@Override
public SSPGameBuilder changeMaximumComputationTimePerMove(final int newMaxComputationTimePerMove) {
this.maxComputationTimePerMove = newMaxComputationTimePerMove;
return this;
}
@Override
public SSPGameBuilder changeObserverFactoryProvider(final ObserverFactoryProvider newObserverFactoryProvider) {
this.observerFactoryProvider = newObserverFactoryProvider;
return this;
}
@Override
public SSPGame build(final int id) throws GameException, InterruptedException {
if (!this.firstPlayer.isPresent() || !this.secondPlayer.isPresent()) {
throw new GameException("A SSP game needs two players.");
}
final SSPStateImpl initialState = new SSPStateImpl(this.firstPlayer.get(), this.secondPlayer.get());
final Map<String, SSPStrategy> strategies = new LinkedHashMap<>();
strategies.put(initialState.getFirstPlayer().getName(), this.firstPlayerStrategy.orElseThrow());
strategies.put(initialState.getSecondPlayer().getName(), this.secondPlayerStrategy.orElseThrow());
return new SSPGameImpl(
id,
initialState,
strategies,
this.maxComputationTimePerMove,
AbstractSSPMove.class::isInstance,
this.observerFactoryProvider);
}
public ObserverFactoryProvider getObserverFactoryProvider() {
return observerFactoryProvider;
}
public int getMaxComputationTimePerMove() {