{"id":18647622,"url":"https://github.com/artcom/hsm-js","last_synced_at":"2025-04-11T13:30:48.850Z","repository":{"id":17913808,"uuid":"20877331","full_name":"artcom/hsm-js","owner":"artcom","description":"hierarchial state machine for javascript","archived":false,"fork":false,"pushed_at":"2018-08-24T12:28:27.000Z","size":463,"stargazers_count":6,"open_issues_count":1,"forks_count":2,"subscribers_count":22,"default_branch":"master","last_synced_at":"2024-10-30T17:12:38.783Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://artcom.github.io/hsm-js/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/artcom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"License","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-06-16T08:11:02.000Z","updated_at":"2023-03-03T21:50:11.000Z","dependencies_parsed_at":"2022-08-30T08:30:29.399Z","dependency_job_id":null,"html_url":"https://github.com/artcom/hsm-js","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artcom%2Fhsm-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artcom%2Fhsm-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artcom%2Fhsm-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artcom%2Fhsm-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/artcom","download_url":"https://codeload.github.com/artcom/hsm-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223469141,"owners_count":17150283,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T06:27:11.400Z","updated_at":"2024-11-07T06:27:12.034Z","avatar_url":"https://github.com/artcom.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hierarchial State Machine for Javascript\n\n[![Build Status][BS img]][Build Status] [API docs](http://artcom.github.io/hsm-js/HSM.html)\n\n## Description\n\nSimple, yet powerful hierarchial state machine framework. Supports Sub-Statemachines (nested states) and Parallel-Statemachines (orthogonal regions) and entry and exit handlers.  \n\nThe following state machine is used [in the tests](test/testAdvanced.js) and this documentation to illustrate the features.\n\n![advanced state machine example](doc/advanced.png \"advanced state machine example\")\n\n## States and State Machines\n\nStates are specified by creating HSM.State instances. They are then composed to a state machine by passing them to the HSM.StateMachine constructor.\n\n        var a1 = new HSM.State(\"a1\");\n        var a2 = new HSM.State(\"a2\");\n        var a3 = new HSM.State(\"a3\");\n        var a = new HSM.StateMachine([a1,a2,a3]);\n\nBy convention, the first state passed is the initial state. The state machine is then initialized by HSM.StateMachine.init():\n\n        a.init();\n\nThis starts the state machine and activates the initial state, calling its entry handler (see below). The state machine is now ready to \nhandle events.\n\n\n## Actions and State Transitions\n\nEach state has a map of event handlers. These handlers will be called when the state receives the respective event.\nEvent handlers are added to the handler[] array of each state:\n\n    a3.handler.T3 = { target: a1 };\n\nThis specifies a transition from State to newState for event. Additionally, an action can be added to the transition:\n\n    a2.handler.T2 = { target: a3, action: function() { this.emit('T3') };\n\nEvents are triggered by calling the StateMachine.handleEvent() method. This can even be done inside an event handler's actionFunc.  If an event is \ntriggered while an event is being handled it will be queued until the current event completes. This is known as the run-to-completion (RTC) execution model.  \n\n## Guards \n\nGuards (or guard conditions) affect the behaviour of a state machine by enabling actions or transitions only when they evaluate to TRUE and disabling them when they evaluate to FALSE. \nWhen using guards, multiple event handlers can be bound to a single trigger with a guard. Each guard is evaluated until one returns true. The respective handler is then invoked (after calling\nthe usual exit handler).\n\n        a1.handler.T1 = [\n            { target: a2, guard: function (_,_,data) { return data==true; } },\n            { target: a3, guard: function (_,_,data) { return data==false; } }\n        ];\n\n## Entry and Exit handlers\n\nEach state can have a `on_entry` and/or `on_exit` function. They will be invoked when the state is entered or exited. \n\n## Sub-StateMachines (nested)\n\nState Machines can be nested in other state machines my using the HSM.Sub adapter class. All events are propgated into the sub-state machines, \nand the sub state machine is initialized and torn down on entry/exit of its containing state.\n\n        var a1 = new HSM.State(\"a1\");\n        var a2 = new HSM.State(\"a2\");\n        var a3 = new HSM.State(\"a3\");\n\n        var a = new HSM.Sub(\"a\", new HSM.StateMachine([a1, a2, a3]));\n\nSince _a_ is a State it can be used to construct the _top_ state machine, can have event handlers and entry and exit handlers.\n\n## Least Common Ancestor Algorithm\n\nA transition can span nested state machines. In the case, the transition is performed by the least common ancestor (LCA) of the\nsource and target transition. All exit handlers from the source transition up to (but not including) the LCA are called, the transition action is\ncalled, then all entry handlers from the LCA down to the target state are called. Note that the initial states of these targeted state machines are not \nentered - the explict target state path is used instead. If the target state is itself composite, it's nested states will be initialized in\nthe normal manner (with their respective initial states).\n\nFor example. T4 will fire `a3:on_exit, a:on_exit`, exiting up to the LCA, then `b:on_entry, b2:on_entry` entering to the target,\nfollowed by `b21:on_entry` since it is the initial state of `b2`. \n\n## Parallel State-Machines (orthogonal regions)\n\nParallel state machines are constructed with the HSM.Parallel adapter class.\n\n        var c11 = new HSM.State(\"c11\");\n        var c12 = new HSM.State(\"c12\");\n    \n        var c21 = new HSM.State(\"c21\");\n        var c22 = new HSM.State(\"c22\");\n        \n        var c = new HSM.Parallel(\"c\", new HSM.StateMachine([c11, c12]), \n                                      new HSM.StateMachine([c21, c22]));\n\nagain, _c_ is a State and can be used to construct the _top_ state machine. It can have event handlers and entry and exit handlers.\n\n## External and Local Transitions\n\nA transition can be declared local by adding the optional paramater `kind: 'local'`:\n\n        b22.handler.T9 = {\n            target: b,\n            kind: 'local'\n        };\n\nIf the source is an ancestor of the target (or the otherway around) the ancestor's exit and entry handlers will not be called. In other cases, the local transition\nis identical to an external transition (the default).\n\n## Internal Transitions\n\nA transition can be declared internal by adding the optional paramater `kind: 'internal'` and an action:\n\n        b1.handler.T10 = {\n            target: b1,\n            kind: 'internal',\n            action: function (theData) {\n                // do something ...\n            }\n        };\n\nThe target state can be either omitted or be identical to the source state.\n\n[Build Status]: https://travis-ci.org/artcom/hsm-js\n[BS img]: https://travis-ci.org/artcom/hsm-js.png\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartcom%2Fhsm-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fartcom%2Fhsm-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartcom%2Fhsm-js/lists"}