Last active
July 28, 2016 14:38
-
-
Save beccadax/8b89db56de8bd113b6c5371484a81305 to your computer and use it in GitHub Desktop.
HierarchicalTurnstyleState with Functioning/Broken implemented with a generic type
This file contains hidden or 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
// Untested; consider this a sketch | |
typealias HierarchicalTurnstyleState = StatusState<FunctioningTurnstyleState> | |
enum StatusState<MachineState: StateType>: StateType { | |
case Functioning(MachineState) | |
case Broken(oldState: MachineState) | |
typealias Event = StatusEvent<MachineState.Event> | |
typealias Command = MachineState.Command | |
static let initialState = .Functioning(MachineState.initialState) | |
mutating func handleEvent(event: Event) -> Command? { | |
switch (self, event) { | |
case (.Functioning(let state), .MachineDidFail): | |
self = .Broken(oldState: state) | |
case (.Functioning(var state), .Machine(let event)): | |
let command = state.handleEvent(event) | |
self = .Functioning(state) | |
return command | |
case (.Broken(let oldState), .MachineRepairDidComplete): | |
self = .Functioning(oldState) | |
default: | |
break | |
} | |
return nil | |
} | |
} | |
enum StatusEvent<MachineEvent> { | |
case MachineDidFail | |
case MachineRepairDidComplete | |
case Machine(MachineEvent) | |
} | |
// If you want to maintain source compatibility when constructing events: | |
extension StatusEvent where MachineEvent == FunctioningTurnstyleState { | |
static func InsertCoin(value: Int) -> StatusEvent { | |
return .Machine(.InsertCoin(value: value)) | |
} | |
static var AdmitPerson: StatusEvent { | |
return .Machine(.AdmitPerson) | |
} | |
} | |
enum FunctioningTurnstyleState: StateType { | |
case Locked(credit: Int) | |
case Unlocked | |
enum Event { | |
case InsertCoin(value: Int) | |
case AdmitPerson | |
} | |
enum Command { | |
case SoundAlarm | |
case CloseDoors | |
case OpenDoors | |
} | |
static let initialState = FunctioningTurnstyleState.Locked(credit: 0) | |
private static let farePrice = 50 | |
mutating func handleEvent(event: Event) -> Command? { | |
// Now somewhat simpler because the turnstyle can't be broken. | |
switch (self, event) { | |
case (.Locked(let credit), .InsertCoin(let value)): | |
let newCredit = credit + value | |
if newCredit >= TurnstyleState.farePrice { | |
self = .Unlocked | |
return .OpenDoors | |
} else { | |
self = .Locked(credit: newCredit) | |
} | |
case (.Locked, .AdmitPerson): | |
return .SoundAlarm | |
case (.Unlocked, .AdmitPerson): | |
self = .Locked(credit: 0) | |
return .CloseDoors | |
default: | |
break // or maybe throw, etc | |
} | |
return nil | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment