91 lines
2.5 KiB
Go
91 lines
2.5 KiB
Go
package westworldwithmessaging
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// cookStew is the Go version of the (not yet pasted) singleton class
|
|
// CookStew from the book. Same pattern as every other state:
|
|
// unexported type, one shared instance, reached only through the
|
|
// function below.
|
|
type cookStew struct{}
|
|
|
|
var (
|
|
cookStewInstance *cookStew
|
|
cookStewOnce sync.Once
|
|
)
|
|
|
|
// CookStew is the Go stand-in for "CookStew::Instance()".
|
|
func CookStew() *cookStew {
|
|
cookStewOnce.Do(func() {
|
|
cookStewInstance = &cookStew{}
|
|
})
|
|
return cookStewInstance
|
|
}
|
|
|
|
var _ State[Elsa] = (*cookStew)(nil)
|
|
|
|
// Execute and Exit weren't pasted to us directly either, but a
|
|
// sample run of the book's program makes their behavior clear
|
|
// enough to fill in: Execute prints "Fussin' over food" once per
|
|
// tick while the stew is in the oven (waiting for the delayed
|
|
// Msg_StewReady reminder to arrive), and Exit announces taking the
|
|
// stew out and putting it on the table, right before switching back
|
|
// to DoHousework.
|
|
|
|
// Enter puts the stew in the oven (if one isn't already cooking) and
|
|
// sends a delayed message to herself, reminding her to take it out
|
|
// once it's ready.
|
|
func (s *cookStew) Enter(e *Elsa) {
|
|
if !e.Cooking() {
|
|
fmt.Printf("\n%s: Puttin' the stew in the oven", GetNameOfEntity(e.ID()))
|
|
|
|
// send a delayed message to myself so that I know when to take
|
|
// the stew out of the oven
|
|
Dispatch.DispatchMessage(
|
|
1.5, // time delay
|
|
e.ID(), // sender ID
|
|
e.ID(), // receiver ID
|
|
int(MsgStewReady), // the message
|
|
NoAdditionalInfo, // no extra info attached
|
|
)
|
|
e.SetCooking(true)
|
|
}
|
|
}
|
|
|
|
func (s *cookStew) Execute(e *Elsa) {
|
|
fmt.Printf("\n%s: Fussin' over food", GetNameOfEntity(e.ID()))
|
|
}
|
|
|
|
func (s *cookStew) Exit(e *Elsa) {
|
|
fmt.Printf("\n%s: Puttin' the stew on the table", GetNameOfEntity(e.ID()))
|
|
}
|
|
|
|
// OnMessage handles the delayed reminder Enter sent to herself: once
|
|
// the stew's ready, take it out, let Bob know dinner's on the table,
|
|
// and go back to the ordinary housework state.
|
|
func (s *cookStew) OnMessage(e *Elsa, msg Telegram) bool {
|
|
switch MessageType(msg.Msg) {
|
|
case MsgStewReady:
|
|
fmt.Printf("\nMessage received by %s at time: %.5f", GetNameOfEntity(e.ID()), Clock.GetCurrentTime())
|
|
fmt.Printf("\n%s: Stew ready! Let's eat", GetNameOfEntity(e.ID()))
|
|
|
|
// let hubby know the stew is ready
|
|
Dispatch.DispatchMessage(
|
|
SendMsgImmediately,
|
|
e.ID(),
|
|
entMinerBob,
|
|
int(MsgStewReady),
|
|
NoAdditionalInfo,
|
|
)
|
|
|
|
e.SetCooking(false)
|
|
e.FSM().ChangeState(DoHousework())
|
|
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|