Skip to content

Instantly share code, notes, and snippets.

@anatollupacescu
Last active May 31, 2017 15:03
Show Gist options
  • Save anatollupacescu/eaaf682451093872229d to your computer and use it in GitHub Desktop.
Save anatollupacescu/eaaf682451093872229d to your computer and use it in GitHub Desktop.
An event sequence validator for Blackjack
package demo;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import org.hamcrest.CoreMatchers;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import static org.hamcrest.MatcherAssert.assertThat;
abstract class EventSequenceValidator<A, E> {
protected class Transition {
E event;
State state;
public Transition(E event, State state) {
this.event = event;
this.state = state;
}
}
protected class State {
A await;
List<Transition> transitions;
State setAwait(A await) {
this.await = await;
return this;
}
State setTransitions(Transition... transitions) {
this.transitions = Arrays.asList(transitions);
return this;
}
Transition getTransitionForEvent(E e) {
for (Transition t : transitions) {
if (t.event == e) return t;
}
return null;
}
@Override
public String toString() {
return await.toString();
}
}
private State currentState;
public State getCurrentState() {
Preconditions.checkNotNull(currentState, "Current state is null. Make sure you called startWith method");
return currentState;
}
protected void startWith(State initial) {
currentState = initial;
}
public void acceptEvent(final E event) {
currentState = Optional.fromNullable(getCurrentState().getTransitionForEvent(event))
.transform(new Function<Transition, State>() {
@Override
public State apply(Transition transition) {
return transition.state;
}
})
.or(new Supplier<State>() {
@Override
public State get() {
throw new IllegalStateException(String.format("State waiting for %s can not accept event %s", currentState, event));
}
});
}
}
enum AWAIT {
INITIAL_BET,
USER_CARD_1,
USER_CARD_2,
DEALER_CARD_1,
USER_DECISION_1,
USER_DECISION_2,
DEALER_DRAW
}
enum EVENT {
CARD_TO_USER,
CARD_TO_DEALER,
HIT,
STAND,
BET
}
class BJEventSequenceValidator extends EventSequenceValidator<AWAIT, EVENT> {
final State initialBet = new State();
final State cardToUser1 = new State();
final State cardToDealer1 = new State();
final State cardToUser2 = new State();
final State userDecision1 = new State();
final State userDecision2 = new State();
final State dealerDraw = new State();
public BJEventSequenceValidator() {
initialBet.setAwait(AWAIT.INITIAL_BET).setTransitions(new Transition(EVENT.BET, cardToUser1));
cardToUser1.setAwait(AWAIT.USER_CARD_1).setTransitions(new Transition(EVENT.CARD_TO_USER, cardToDealer1));
cardToDealer1.setAwait(AWAIT.DEALER_CARD_1).setTransitions(new Transition(EVENT.CARD_TO_DEALER, cardToUser2));
cardToUser2.setAwait(AWAIT.USER_CARD_2).setTransitions(new Transition(EVENT.CARD_TO_USER, userDecision1));
userDecision1.setAwait(AWAIT.USER_DECISION_1)
.setTransitions(new Transition(EVENT.STAND, dealerDraw),
new Transition(EVENT.HIT, userDecision1),
new Transition(EVENT.BET, userDecision2));
userDecision2.setAwait(AWAIT.USER_DECISION_2)
.setTransitions(new Transition(EVENT.STAND, dealerDraw),
new Transition(EVENT.HIT, userDecision2));
dealerDraw.setAwait(AWAIT.DEALER_DRAW).setTransitions(new Transition(EVENT.CARD_TO_DEALER, dealerDraw));
startWith(initialBet);
}
}
public class BJEventSequenceValidatorTests {
@Test
public void testInitialState() {
BJEventSequenceValidator BJEventSequenceValidator = new BJEventSequenceValidator();
assertThat(BJEventSequenceValidator, CoreMatchers.notNullValue());
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.INITIAL_BET));
}
@Test
public void testBet() {
BJEventSequenceValidator BJEventSequenceValidator = new BJEventSequenceValidator();
BJEventSequenceValidator.acceptEvent(EVENT.BET);
assertThat(BJEventSequenceValidator, CoreMatchers.notNullValue());
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_CARD_1));
}
@Test(expected = IllegalStateException.class)
public void testIllegalMove() {
BJEventSequenceValidator BJEventSequenceValidator = new BJEventSequenceValidator();
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
}
@Test
public void testEndToEndStand() {
BJEventSequenceValidator BJEventSequenceValidator = new BJEventSequenceValidator();
BJEventSequenceValidator.acceptEvent(EVENT.BET);
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_USER);
assertThat(BJEventSequenceValidator, CoreMatchers.notNullValue());
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_CARD_1));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_CARD_2));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_USER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_1));
BJEventSequenceValidator.acceptEvent(EVENT.STAND);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
}
@Test
public void testEndToEndHit() {
BJEventSequenceValidator BJEventSequenceValidator = new BJEventSequenceValidator();
BJEventSequenceValidator.acceptEvent(EVENT.BET);
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_USER);
assertThat(BJEventSequenceValidator, CoreMatchers.notNullValue());
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_CARD_1));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_CARD_2));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_USER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_1));
BJEventSequenceValidator.acceptEvent(EVENT.HIT);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_1));
BJEventSequenceValidator.acceptEvent(EVENT.HIT);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_1));
BJEventSequenceValidator.acceptEvent(EVENT.HIT);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_1));
BJEventSequenceValidator.acceptEvent(EVENT.STAND);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
}
@Test
public void testEndToEndBetStand() {
BJEventSequenceValidator BJEventSequenceValidator = new BJEventSequenceValidator();
BJEventSequenceValidator.acceptEvent(EVENT.BET);
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_USER);
assertThat(BJEventSequenceValidator, CoreMatchers.notNullValue());
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_CARD_1));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_CARD_2));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_USER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_1));
BJEventSequenceValidator.acceptEvent(EVENT.BET);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_2));
BJEventSequenceValidator.acceptEvent(EVENT.STAND);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
}
@Test
public void testEndToEndBetHit() {
BJEventSequenceValidator BJEventSequenceValidator = new BJEventSequenceValidator();
BJEventSequenceValidator.acceptEvent(EVENT.BET);
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_USER);
assertThat(BJEventSequenceValidator, CoreMatchers.notNullValue());
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_CARD_1));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_CARD_2));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_USER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_1));
BJEventSequenceValidator.acceptEvent(EVENT.BET);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_2));
BJEventSequenceValidator.acceptEvent(EVENT.HIT);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.USER_DECISION_2));
BJEventSequenceValidator.acceptEvent(EVENT.STAND);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
BJEventSequenceValidator.acceptEvent(EVENT.CARD_TO_DEALER);
assertThat(BJEventSequenceValidator.getCurrentState().await, CoreMatchers.equalTo(AWAIT.DEALER_DRAW));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment