Created
March 17, 2018 20:56
-
-
Save sramam/fba55f5325a8c398870292e1f3cada05 to your computer and use it in GitHub Desktop.
A simple bank-account FSM, implemented in javascript-state-machine
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
const StateMachine = require('javascript-state-machine'); | |
const Account = StateMachine.factory({ | |
init: 'open', | |
transitions: [ | |
// open state | |
{name: 'deposit', from: 'open', to: 'open'}, | |
{name: 'withdraw', from: 'open', to: 'open'}, | |
{name: 'available', from: 'open', to: 'open'}, | |
{name: 'placeHold', from: 'open', to: 'held'}, | |
{name: 'close', from: 'open', to: 'closed'}, | |
// held state | |
{name: 'deposit', from: 'held', to: 'held'}, | |
{name: 'available', from: 'held', to: 'held'}, | |
{name: 'removeHold', from: 'held', to: 'open'}, | |
{name: 'close', from: 'held', to: 'closed'}, | |
// closed state | |
{name: 'reopen', from: 'closed', to: 'open'}, | |
], | |
data: function(accountBalance) { | |
return { accountBalance: accountBalance || 0 }; | |
}, | |
methods:{ | |
onDeposit: function(lc, amount) { | |
if (amount < 0) { | |
console.log(`ERROR: cannot deposit a negative amount`); | |
return false; | |
} | |
this.accountBalance += amount; | |
}, | |
onWithdraw: function(lc, amount) { | |
if (this.accountBalance < amount) { | |
console.log(`ERROR: ${amount} is more than you have in the account! Cannot withdraw this amount.`); | |
return false; | |
} | |
this.accountBalance -= amount; | |
}, | |
onInvalidTransition: function(event, from, to) { | |
console.log(`ERROR: It's not possible to ${event} from an account that is ${from} `); | |
}, | |
balance: function() { | |
if (!this.can('available')) { | |
console.log(`ERROR: cannot call available in ${this.state}`); | |
return false; | |
} | |
return this.accountBalance; | |
}, | |
statement: function () { | |
console.log(`Account is ${this.state} with a balance of ${this.balance()}`) | |
} | |
} | |
}); | |
const account = new Account(10); | |
// legal operations on an open account | |
account.statement(); | |
account.deposit(5); | |
account.statement(); | |
account.withdraw(10); | |
account.statement(); | |
account.withdraw(10); | |
account.statement(); | |
// moving states | |
account.placeHold(); | |
account.statement(); | |
account.removeHold(); | |
account.close(); | |
account.statement(); | |
account.reopen(); | |
account.statement(); | |
// move state to test illegal operations | |
account.placeHold(); | |
account.withdraw(1); | |
account.removeHold(); | |
account.withdraw(1); | |
account.statement(); | |
// Visualization also built in | |
const visualize = require('javascript-state-machine/lib/visualize'); | |
const fs = require('fs'); | |
const viz = require('viz.js'); | |
const dot = visualize(account); | |
const svg = viz(dot, { format: "svg"}); | |
fs.writeFileSync('./account.svg', svg, 'utf8'); | |
fs.writeFileSync('./account.dot', dot, 'utf8'); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment