Last active
May 31, 2017 15:03
-
-
Save anatollupacescu/eaaf682451093872229d to your computer and use it in GitHub Desktop.
An event sequence validator for Blackjack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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