func getLocationRules() fsm.Ruleset { rules := fsm.Ruleset{} rules.AddTransition(fsm.T{"town", "forest"}) rules.AddTransition(fsm.T{"forest", "battle"}) rules.AddRule(fsm.T{"town", "forest"}, func(subject fsm.Stater, goal fsm.State) bool { println("You must have enough energy to go to forest.") return true }) return rules }
func NewWindowRules() fsm.Ruleset { rules := fsm.Ruleset{} rules.AddTransition(fsm.T{"title", "character selection"}) rules.AddTransition(fsm.T{"character selection", "game"}) rules.AddTransition(fsm.T{"character selection", "create character"}) rules.AddRule(fsm.T{"title", "character selection"}, func(subject fsm.Stater, goal fsm.State) bool { return true }) return rules }
func NewBattleRules() fsm.Ruleset { rules := fsm.Ruleset{} rules.AddTransition(fsm.T{"wait", "attack"}) rules.AddTransition(fsm.T{"wait", "run"}) rules.AddTransition(fsm.T{"wait", "use item"}) rules.AddTransition(fsm.T{"wait", "end"}) rules.AddRule(fsm.T{"wait", "attack"}, func(subject fsm.Stater, goal fsm.State) bool { return true }) return rules }
func TestRulesetParallelGuarding(t *testing.T) { rules := fsm.Ruleset{} rules.AddTransition(fsm.T{"pending", "started"}) rules.AddTransition(fsm.T{"started", "finished"}) // Add two failing rules, the slow should be caught first rules.AddRule(fsm.T{"started", "finished"}, func(subject fsm.Stater, goal fsm.State) bool { time.Sleep(1 * time.Second) t.Error("Slow rule should have been short-circuited") return false }) rules.AddRule(fsm.T{"started", "finished"}, func(subject fsm.Stater, goal fsm.State) bool { return false }) st.Expect(t, rules.Permitted(&Thing{State: "started"}, "finished"), false) }
func BenchmarkRulesetParallelGuarding(b *testing.B) { rules := fsm.Ruleset{} rules.AddTransition(fsm.T{"pending", "started"}) rules.AddTransition(fsm.T{"started", "finished"}) // Add two failing rules, one very slow and the other terribly fast rules.AddRule(fsm.T{"started", "finished"}, func(subject fsm.Stater, goal fsm.State) bool { time.Sleep(1 * time.Second) return false }) rules.AddRule(fsm.T{"started", "finished"}, func(subject fsm.Stater, goal fsm.State) bool { return false }) b.ResetTimer() for i := 0; i < b.N; i++ { rules.Permitted(&Thing{State: "started"}, "finished") } }
func BenchmarkRulesetRuleForbids(b *testing.B) { // Here, we explicity create a transition that is forbidden. This simulates an // otherwise valid transition that would be denied based on a user role or the like. // It should be slower than a standard invalid transition, since we have to // actually execute a function to perform the check. The first guard to // fail (returning false) will short circuit the execution, getting some some speed. rules := fsm.Ruleset{} rules.AddTransition(fsm.T{"pending", "started"}) rules.AddRule(fsm.T{"started", "finished"}, func(subject fsm.Stater, goal fsm.State) bool { return false }) some_thing := &Thing{State: "started"} b.ResetTimer() for i := 0; i < b.N; i++ { rules.Permitted(some_thing, "finished") } }