package gameengine;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import common.CryptoUtil;
import common.Digest;
import common.StateMachineCheckpointListener;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import statemachine.InvalidStateMachineOperationException;
import statemachine.Operation;
import statemachine.StateMachine;
import java.util.List;
/**
* Created by andrew on 11/30/14.
*/
public class ChineseCheckersStateMachine implements StateMachine<ChineseCheckersState, Operation<ChineseCheckersState>> {
private static Logger LOG = LogManager.getLogger(ChineseCheckersStateMachine.class);
private ChineseCheckersState state;
private int numOperationsApplied;
private static final int CHECKPOINT_INTERVAL = 100;
private int lastCheckpointed;
private Optional<Digest> checkpointDigest;
private List<StateMachineCheckpointListener> listeners;
public ChineseCheckersStateMachine(ChineseCheckersState state) {
this.state = state;
this.numOperationsApplied = 0;
this.lastCheckpointed = -1; // never checkpointed
this.checkpointDigest = Optional.absent();
this.listeners = Lists.newArrayList();
}
@Override
synchronized public void applyOperation(Operation<ChineseCheckersState> op) throws InvalidStateMachineOperationException {
LOG.info("Applying operation: " + op);
if (!op.isValid(this.getState())) { throw new InvalidStateMachineOperationException(); }
op.apply(this.getState());
numOperationsApplied++;
// checkpointing currently blocks application of moves
if ((numOperationsApplied % CHECKPOINT_INTERVAL) == 0) {
LOG.info("Checkpointing after operation " + numOperationsApplied);
checkpointDigest = Optional.of(CryptoUtil.computeDigest(this));
lastCheckpointed = numOperationsApplied;
for (StateMachineCheckpointListener listener : listeners) {
listener.notifyOnCheckpointed(lastCheckpointed, checkpointDigest.get());
}
}
}
synchronized public ChineseCheckersState getState() {
return state;
}
synchronized public void setState(ChineseCheckersState newState) {
state = newState;
}
@Override
public void addCheckpointListener(StateMachineCheckpointListener listener) {
listeners.add(listener);
}
}