Skip to content

Commit

Permalink
Adding Examples from Repo
Browse files Browse the repository at this point in the history
  • Loading branch information
ifandelse committed Jun 20, 2015
1 parent 99013f2 commit 06f9e42
Show file tree
Hide file tree
Showing 65 changed files with 3,190 additions and 11 deletions.
12 changes: 12 additions & 0 deletions example/atm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# ATM Example

An example application where one FSM acts as the "brains" for an ATM machine (AtmFsm.js), and another controls how the nav bar is displayed (NavFsm.js), depending on the state of the application.

There are two sets of credentials that will work with this sample app:

* acct 123456789, pin 8675
* acct 987654321, pin 3090

This example application was intentionally written without message-bus interaction in order to demonstrate direct API usage. For a message-bus-integrated example, please see the "load" sample app.

Even though messaging is not actively used in this example, it *does* demonstrate the auto-wireup to amplify.js's pub/sub. The auto-wireup to amplify provides a wiretap, which causes any FSM events to be printed to the console.
40 changes: 40 additions & 0 deletions example/atm/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title>ATM State Machine Example</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script type="text/javascript" src="../../bower/lodash/dist/lodash.js"></script>
<script type="text/javascript" src="../../bower/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../../bower/backbone/backbone-min.js"></script>
<script type="text/javascript" src="/ext/infuser_all.js"></script>
<script type="text/javascript" src="../../bower/amplify/lib/amplify.js"></script>
<script type="text/javascript" src="js/amplify.diagnostics.js"></script>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/machina.js/1.1.0/machina.js"></script>
<script type="text/javascript" src="../../bower/accounting/accounting.js"></script>
<script type="text/javascript" src="js/appConfig.js"></script>
<script type="text/javascript" src="js/Repository.js"></script>
<script type="text/javascript" src="js/router.js"></script>
<script type="text/javascript" src="js/AtmFsm.js"></script>
<script type="text/javascript" src="js/NavFsm.js"></script>
<script type="text/javascript" src="js/models/AppModel.js"></script>
<script type="text/javascript" src="js/models/AccountInfo.js"></script>
<script type="text/javascript" src="js/models/LoginModel.js"></script>
<script type="text/javascript" src="js/models/DepositModel.js"></script>
<script type="text/javascript" src="js/models/WithdrawalModel.js"></script>
<script type="text/javascript" src="js/models/ResultModel.js"></script>
<script type="text/javascript" src="js/views/AccountView.js"></script>
<script type="text/javascript" src="js/views/ResultView.js"></script>
<script type="text/javascript" src="js/views/DepositView.js"></script>
<script type="text/javascript" src="js/views/WithdrawalView.js"></script>
<script type="text/javascript" src="js/views/LoginView.js"></script>
<script type="text/javascript" src="js/views/NavView.js"></script>
<script type="text/javascript" src="js/views/AppView.js"></script>
<script type="text/javascript" src="js/main.js"></script>
</head>
<body>
<div id="container">
<div id="content"></div>
</div>
</body>
</html>
60 changes: 60 additions & 0 deletions example/atm/js/AtmFsm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
This FSM generates the following custom events:
"Initialized",
"Authorized",
"UnAuthorized",
"Deposit",
"Withdrawal",
"OverLimit",
"Result"
*/
var Atm = function() {
var fsm;
fsm = new machina.Fsm( {
initialState: "uninitialized",
states: {
"uninitialized": {
"initialize": function() {
// TODO: any other init work here...
this.emit( "Initialized" );
this.transition( "unauthorized" );
}
},
"unauthorized": {
_onEnter: function() {
this.emit( "UnAuthorized", { msg: "Please enter your account and PIN." } );
},
"*": function() {
this.emit( "UnAuthorized", { msg: "You must authenticate first." } );
},
authorize: function( credentials ) {
if ( authRepository.authorize( credentials.acct, credentials.pin ) ) {
this.acct = credentials.acct;
this.transition( "authorized" );
return;
}
this.emit( "UnAuthorized", { msg: "Invalid Account and/or PIN." } );
}
},
"authorized": {
_onEnter: function() {
this.emit( "Authorized", { acct: this.acct } );
},
deposit: function( amount ) {
var result = clientRepository.deposit( this.acct, amount );
this.emit( "Result", result );
},
withdrawal: function( amount ) {
var result = clientRepository.withdrawal( this.acct, amount );
this.emit( "Result", result );
},
deauthorize: function() {
authRepository.deauthorize( this.acct );
delete this.acct;
this.transition( "unauthorized" );
}
}
}
} );
return fsm;
};
33 changes: 33 additions & 0 deletions example/atm/js/NavFsm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
var NavFsm = function( appFsm, navView ) {
var fsm = new machina.Fsm( {
initialState: "unauthorized",
states: {
"unauthorized": {
_onEnter: function() {
navView.unAuthLayout();
},
"*": function() {
navView.unAuthLayout();
}
},
"authorized": {
"*": function() {
navView.authLayout();
},
"deposit": function() {
navView.depositLayout();
},
"withdrawal": function() {
navView.withdrawalLayout();
}
}
}
} );
appFsm.on( "Authorized", function() {
fsm.transition( "authorized" );
} );
appFsm.on( "UnAuthorized", function() {
fsm.transition( "unauthorized" );
} );
return fsm;
};
78 changes: 78 additions & 0 deletions example/atm/js/Repository.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
var clientRepository, authRepository, resources, accounts, currentAcct;
( function( _ ) {
var results = { };
accounts = {
"123456789": {
pin: "8675",
name: "Elwin Ransom",
limit: 20000,
balance: 100000
},
"987654321": {
pin: "3090",
name: "Edward Weston",
limit: 400,
balance: 300
}
};
authRepository = {
authorize: function( acct, pin ) {
var authed = accounts[acct] && accounts[acct].pin === pin;
if ( authed ) {
currentAcct = acct;
return true;
}
return false;
},

deauthorize: function( acct ) {
if ( currentAcct === acct ) {
currentAcct = undefined;
return true;
}
return false;
}
};
clientRepository = {
withdrawal: function( acct, amount ) {
var current = accounts[currentAcct],
newBal = current.balance - amount,
result = {
status: ( amount > current.limit ) ? "OverLimit" : ( newBal < 0 ) ? "InsufficientFunds" : "Successful",
transactionAmount: amount
};
if ( result.status === "Successful" )
current.balance = newBal;
if ( !results[acct] ) {
results[acct] = [];
}
results[acct].push( $.extend( true, { transactionType: "Withdrawal" }, accounts[ currentAcct ], result ) );
return { acct: acct, resultId: results[acct].length - 1 };
},
deposit: function( acct, amount ) {
accounts[ currentAcct ].balance += amount;
if ( !results[acct] ) {
results[acct] = [];
}
results[acct].push( $.extend( true, { transactionType: "Deposit" }, accounts[ currentAcct ], { status: "Successful", transactionAmount: amount } ) );
return { acct: acct, resultId: results[acct].length - 1 };
}
};
resources = {
result: {
read: function( model, options ) {
options.success( results[model.acct][model.id] );
}
},
accountInfo: {
read: function( model, options ) {
options.success( accounts[model.id] );
}
}
};

Backbone.sync = function( method, model, options ) {
var modelType = model.get( "modelType" );
resources[modelType][method]( model.toJSON(), options );
};
} )( _ );
11 changes: 11 additions & 0 deletions example/atm/js/amplify.diagnostics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var orig = amplify.publish;

amplify.publish = function( topic, message ) {
try {
console.log( topic + " " + JSON.stringify( message ) );
}
catch ( exception ) {
console.log( topic + " (unable to serialize payload)" );
}
orig.call( this, topic, message );
}
17 changes: 17 additions & 0 deletions example/atm/js/appConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
( function( $, _, infuser, undefined ) {
var infuserDefault = infuser.defaults;

infuser.defaults = $.extend( true, infuserDefault, {
templateUrl: "/example/atm/templates",
bindingInstruction: function( template, model ) {
return template( model );
},
render: function( target, template ) {
$( target ).html( template );
},
useLoadingTemplate: false,
templatePreProcessor: function( template ) {
return _.template( template );
}
} );
} )( jQuery, _, infuser );
80 changes: 80 additions & 0 deletions example/atm/js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
var AtmApplication = function( target ) {
//----------------------------------------------------------------------------
//
// The top level application object
//
//----------------------------------------------------------------------------
var app = {
atm: new Atm(),
models: {
accountInfo: undefined
},
views: {
main: new AppView( { target: target } ),
nav: new NavView(),
login: new LoginView( { target: "#screen" } ),
account: new AccountView( { target: "#screen" } ),
deposit: new DepositView( { target: "#screen" } ),
result: new ResultView( { target: "#screen" } ),
withdrawal: new WithdrawalView( { target: "#screen" } )
},
start: function() {
this.atm.handle( "initialize" );
}
};

app.navFsm = new NavFsm( app.atm, app.views.nav );

//----------------------------------------------------------------------------
//
// Handlers for View Events
//
//----------------------------------------------------------------------------
app.views.main.on( "AppRendered", function() {
app.views.nav.render( app.views.nav.unAuthLayout );
} );

app.views.login.on( "Authenticate", function( model ) {
app.atm.handle( "authorize", model );
} );

app.views.deposit.on( "Deposit", function( amount ) {
app.atm.handle( "deposit", amount );
} );

app.views.withdrawal.on( "Withdrawal", function( amount ) {
app.atm.handle( "withdrawal", amount );
} );

//----------------------------------------------------------------------------
//
// Handlers for App FSM Events
//
//----------------------------------------------------------------------------
app.atm.on( "Initialized", function() {
app.views.main.render();
app.router = new Router( app.atm, app.navFsm, app.views, app.models );
Backbone.history.start( { root: "/example/atm/" } );
} );

app.atm.on( "Authorized", function( data ) {
app.models.accountInfo = new AccountInfo( { id: data.acct } );
app.views.main.model.set( "currentAccount", data.acct ); //TODO = needed?
window.location.hash = "account";
} );

app.atm.on( "UnAuthorized", function() {
window.location.hash = "unauthorized";
} );
app.atm.on( "Result", function( data ) {
app.models.accountInfo.fetch();
window.location.hash = "result/" + data.resultId;
} );

return app;
};

$( function() {
window.atmApp = new AtmApplication( '#content' );
window.atmApp.start();
} );
12 changes: 12 additions & 0 deletions example/atm/js/models/AccountInfo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var AccountInfo = Backbone.Model.extend( {
defaults : {
modelType : "accountInfo",
name : "",
balance : 0,
limit : 0
},

initialize : function () {
this.fetch();
}
} );
11 changes: 11 additions & 0 deletions example/atm/js/models/AccountModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
var AccountModel = Backbone.Model.extend( {
defaults : {
modelType : "account",
name : "",
balance : 0,
limit : 0
},
initialize : function () {

}
} );
3 changes: 3 additions & 0 deletions example/atm/js/models/AppModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var AppModel = Backbone.Model.extend( {
title : "Contrived ATM Example"
} );
6 changes: 6 additions & 0 deletions example/atm/js/models/DepositModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
var DepositModel = Backbone.Model.extend( {
defaults : {
amount : 0,
error : ""
}
} );
7 changes: 7 additions & 0 deletions example/atm/js/models/LoginModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var LoginModel = Backbone.Model.extend( {
defaults : {
acct : "",
pin : "",
error : ""
}
} );
5 changes: 5 additions & 0 deletions example/atm/js/models/ResultModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
var ResultModel = Backbone.Model.extend( {
defaults : {
modelType : "result"
}
} );
Loading

0 comments on commit 06f9e42

Please sign in to comment.