You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.1 KiB
87 lines
2.1 KiB
import nodeFns from './nodeFns';
|
|
import Context from './context';
|
|
import EventEmitter from 'eventemitter3';
|
|
|
|
const SHAPES = {
|
|
START: 'imove-start',
|
|
BRANCH: 'imove-branch',
|
|
BEHAVIOR: 'imove-behavior'
|
|
}
|
|
|
|
export default class Logic extends EventEmitter{
|
|
|
|
constructor(opts = {}) {
|
|
super();
|
|
this.dsl = opts.dsl;
|
|
}
|
|
|
|
get cells() {
|
|
return this.dsl.cells;
|
|
}
|
|
|
|
get nodes() {
|
|
return this.cells.filter(cell => cell.shape !== 'edge');
|
|
}
|
|
|
|
get startNodes() {
|
|
return this.cells.filter(cell => cell.shape === SHAPES.START);
|
|
}
|
|
|
|
get edges() {
|
|
return this.cells.filter(cell => cell.shape === 'edge');
|
|
}
|
|
|
|
_getStartNode(trigger) {
|
|
for(const cell of this.startNodes) {
|
|
if(cell.data.trigger === trigger) {
|
|
return cell;
|
|
}
|
|
}
|
|
}
|
|
|
|
_getNextNode(ctx, curNode, lastRet) {
|
|
for(const edge of this.edges) {
|
|
let isMatched = edge.source.cell === curNode.id;
|
|
// NOTE: if it is a imove-branch node, each port's condition should be tested whether it is matched
|
|
if(curNode.shape === SHAPES.BRANCH) {
|
|
let matchedPort = '';
|
|
const {ports} = curNode.data;
|
|
for(const key in ports) {
|
|
const {condition} = ports[key];
|
|
const ret = new Function('ctx', 'return ' + condition)(ctx);
|
|
if(ret === lastRet) {
|
|
matchedPort = key;
|
|
break;
|
|
}
|
|
}
|
|
isMatched = isMatched && edge.source.port === matchedPort;
|
|
}
|
|
if(isMatched) {
|
|
const nextNodeId = edge.target.cell;
|
|
return this.nodes.find(item => item.id === nextNodeId);
|
|
}
|
|
}
|
|
}
|
|
|
|
_createCtx() {
|
|
const ctx = new Context();
|
|
ctx.emit = this.emit.bind(this);
|
|
return ctx;
|
|
}
|
|
|
|
async invoke(trigger, data) {
|
|
let curNode = this._getStartNode(trigger);
|
|
if(!curNode) {
|
|
return Promise.reject(`Invoke failed! No logic-start named ${trigger} found!`);
|
|
}
|
|
let lastRet;
|
|
const ctx = this._createCtx();
|
|
ctx._reset({payload: data});
|
|
while(curNode) {
|
|
ctx._transitTo(curNode, lastRet);
|
|
const fn = nodeFns[curNode.id];
|
|
lastRet = await fn(ctx);
|
|
curNode = this._getNextNode(ctx, curNode, lastRet);
|
|
}
|
|
}
|
|
}
|
|
|