Skip to content

Instantly share code, notes, and snippets.

@alexsullivan114
Created February 1, 2019 20:42
Show Gist options
  • Save alexsullivan114/67522d9b6f1dc572d18e1780d20c753a to your computer and use it in GitHub Desktop.
Save alexsullivan114/67522d9b6f1dc572d18e1780d20c753a to your computer and use it in GitHub Desktop.
class GameStateMachine(
events: Flowable<Event>,
gameStateManager: GameStateManager,
playHarvester: PlayHarvesterImpl
) {
private var state: GameStateMachineState =
BatterUpState(GameCoordinator(gameStateManager, playHarvester))
val viewStates: Flowable<ViewState> = Flowable.just(state.viewState).concatWith(events
.doOnNext { state = state.consumeEvent(it) }
.map { state.viewState })
}
sealed class ViewState {
class BatterUpViewState(
val batter: Player,
val organizations: Organizations,
val playersOnBase: List<PlayerOnBase>
) : ViewState()
class BatterOptionViewState : ViewState()
class BatterOutViewState : ViewState()
class BatterOutOptionsViewState : ViewState()
class BatterOutFieldViewState(val fielders: List<Position>) : ViewState()
class BatterOnOptionsViewState(val options: List<Option>, val selectedBase: Base) : ViewState()
class BaseRunnerViewState(val playerOnBase: PlayerOnBase) : ViewState()
class BaseRunnerOptionsViewState(val options: List<Option>, val playerOnBase: PlayerOnBase): ViewState()
class AdvanceRunnerViewState(val playerOnBase: PlayerOnBase): ViewState()
}
interface GameStateMachineState {
val viewState: ViewState
fun consumeEvent(event: Event): GameStateMachineState
sealed class Event {
class BatterClick : Event()
class BaseClick(val base: Base) : Event()
class OutClick : Event()
class OccupiedBaseClick(val base: Base) : Event()
class OptionsSelected(val option: Option) : Event()
class OutRecordingBarLeftBtnClick : Event()
class OutRecordingBarRightBtnClick : Event()
class PositionInserted(val position: Position) : Event()
}
}
// Example of a GameStateMachineState
class BaseRunnerState(
private val playerOnBase: PlayerOnBase,
private val gameCoordinator: GameCoordinator
) : GameStateMachineState {
override val viewState: ViewState
get() = BaseRunnerViewState(playerOnBase)
override fun consumeEvent(event: Event): GameStateMachineState {
return when(event) {
is OutClick -> handleOutClick()
is BaseClick -> handleBaseClick(event)
else -> throw IllegalStateException("$this cannot handle $event")
}
}
private fun handleOutClick(): GameStateMachineState {
gameCoordinator.baseRunnerOut(playerOnBase.player)
return BatterUpState(gameCoordinator)
}
private fun handleBaseClick(baseClick: BaseClick): GameStateMachineState {
return BaseRunnerOptionsState(gameCoordinator, PlayerOnBase(playerOnBase.player, baseClick.base))
}
}
// This function is in a top level presenter. I'm sure there's a better way to do this ugly block.
private fun renderViewStateChange(old: ViewState, new: ViewState) {
return when {
(old is BatterUpViewState && new is BatterOptionViewState) -> old.transitionTo(new)
(old is BatterOptionViewState && new is BatterOutViewState) -> old.transitionTo(new)
(old is BatterOutViewState && new is BatterUpViewState) -> old.transitionTo(new)
(old is BatterOutViewState && new is BatterOutOptionsViewState) -> old.transitionTo(new)
(old is BatterOutViewState && new is BatterOutFieldViewState) -> old.transitionTo(new)
(old is BatterOutFieldViewState && new is BatterOutFieldViewState) -> old.transitionTo(new)
(old is BatterOutFieldViewState && new is BatterOutViewState) -> old.transitionTo(new)
(old is BatterOutFieldViewState && new is BatterUpViewState) -> old.transitionTo(new)
(old is BatterOutOptionsViewState && new is BatterUpViewState) -> old.transitionTo(new)
(old is BatterOptionViewState && new is BatterOnOptionsViewState) -> old.transitionTo(new)
(old is BatterOnOptionsViewState && new is BatterOnOptionsViewState) -> old.transitionTo(new)
(old is BatterOnOptionsViewState && new is BatterUpViewState) -> old.transitionTo(new)
(old is BatterUpViewState && new is BaseRunnerViewState) -> old.transitionTo(new)
(old is BaseRunnerViewState && new is BatterUpViewState) -> old.transitionTo(new)
(old is BaseRunnerViewState && new is BaseRunnerOptionsViewState) -> old.transitionTo(new)
(old is BaseRunnerOptionsViewState && new is BaseRunnerOptionsViewState) -> old.transitionTo(
new
)
(old is BaseRunnerOptionsViewState && new is BatterUpViewState) -> old.transitionTo(new)
(old is BatterOnOptionsViewState && new is AdvanceRunnerViewState) -> old.transitionTo(new)
(old is BatterOutOptionsViewState && new is AdvanceRunnerViewState) -> old.transitionTo(new)
(old is BatterOutViewState && new is AdvanceRunnerViewState) -> old.transitionTo(new)
(old is AdvanceRunnerViewState && new is AdvanceRunnerViewState) -> old.transitionTo(new)
(old is AdvanceRunnerViewState && new is BatterUpViewState) -> old.transitionTo(new)
else -> throw IllegalStateException("Invalid view states: Going from $old to $new")
}
}
// Example of one of the `transitionTo` methods.
private fun BatterUpViewState.transitionTo(newState: BatterOptionViewState) {
view.hideBatterButton()
view.showOutButton(this@GamePresenter)
view.showBases(this@GamePresenter, null)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment