example.lua
#!/usr/bin/env lua
package.path = "./src/?.lua;./src/?/init.lua;" .. package.path
local StateMachine = require "statemachine"
local DoorLock = StateMachine({
initial_state = "locked",
states = {
locked = {
enter = function(self, ctx, from)
table.insert(ctx.log, string.format("Door locked (from: %s)", from or "init"))
if from == "unlocked" then
print("š Door auto-locked after closing")
else
print("š Door is locked")
end
end,
leave = function(self, ctx, to)
if to == "unlocked" then
print("ā Unlock successful!")
end
end,
transitions = {
unlocked = function(self, ctx, to)
if ctx.failed_attempts >= ctx.max_attempts then
return nil, "Too many failed attempts. Lock is disabled."
end
table.insert(ctx.log, "Transition: locked -> unlocked")
return true
end,
},
},
unlocked = {
enter = function(self, ctx, from)
table.insert(ctx.log, string.format("Door unlocked (from: %s)", from))
print("š Door is unlocked. You can now open it.")
ctx.failed_attempts = 0 end,
leave = function(self, ctx, to)
if to == "open" then
print("šŖ Opening door...")
end
end,
transitions = {
locked = function(self, ctx, to)
table.insert(ctx.log, "Transition: unlocked -> locked")
return true
end,
open = function(self, ctx, to)
table.insert(ctx.log, "Transition: unlocked -> open")
return true
end,
},
},
open = {
enter = function(self, ctx, from)
table.insert(ctx.log, string.format("Door opened (from: %s)", from))
print("šŖ Door is now open")
end,
leave = function(self, ctx, to)
print("šŖ Closing door...")
end,
transitions = {
unlocked = function(self, ctx, to)
table.insert(ctx.log, "Transition: open -> unlocked")
return true
end,
},
},
},
})
local door, initial_delay = DoorLock({
failed_attempts = 0,
max_attempts = 3,
log = {},
})
if type(initial_delay) == "number" then
print(string.format("ā±ļø Initial delay requested: %s", tostring(initial_delay)))
end
print("\n=== Smart Door Lock Demo ===\n")
print("\n1. Trying to open a locked door:")
if door:has_transition_to("open") then
door:transition_to("open")
else
print("ā Cannot open: door is locked!")
end
print("\n2. Unlocking the door:")
local ok, err = door:transition_to("unlocked")
if not ok then
print(string.format("ā Blocked: %s", err))
end
print("\n3. Opening the unlocked door:")
door:transition_to("open")
print("\n4. Closing the door:")
door:transition_to("unlocked")
print("\n5. Locking the door:")
door:transition_to("locked")
print(string.format("\nš Current state: %s", door:get_current_state()))
print("\nš Activity log:")
local ctx = door:get_context()
for i, entry in ipairs(ctx.log) do
print(string.format(" %d. %s", i, entry))
end
print("\n6. Attempting invalid transition:")
local success, err = pcall(function()
door:transition_to("open") end)
if not success then
print(string.format("ā Error: %s", err:match("([^\n]+)")))
end
print("\n7. Creating a second door from the same class:")
local door2 = DoorLock({ failed_attempts = 0, max_attempts = 3, log = {} })
print(string.format(" Door 1 state: %s", door:get_current_state()))
print(string.format(" Door 2 state: %s", door2:get_current_state()))
door2:transition_to("unlocked")
print(string.format(" Door 1 state: %s (unchanged)", door:get_current_state()))
print(string.format(" Door 2 state: %s (transitioned independently)", door2:get_current_state()))
print("\n=== Demo Complete ===")