2020-11-05 17:01:47 +00:00
|
|
|
/**
|
|
|
|
* @author Martin Karkowski
|
|
|
|
* @email m.karkowski@zema.de
|
|
|
|
* @create date 2020-02-20 19:46:19
|
2020-12-01 12:05:35 +00:00
|
|
|
* @modify date 2020-11-25 07:36:44
|
2020-11-05 17:01:47 +00:00
|
|
|
* @desc [description]
|
|
|
|
*/
|
|
|
|
|
|
|
|
import * as handlebars from "handlebars";
|
|
|
|
import { IParseableTransitionDescription, IParsedLogic } from "../types/interface";
|
|
|
|
import { AbstractParser } from "./default.parser";
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-01 12:05:35 +00:00
|
|
|
|
2020-11-05 17:01:47 +00:00
|
|
|
export class JsParser extends AbstractParser {
|
|
|
|
public variableDefinition(context: IParsedLogic): string {
|
|
|
|
throw new Error("Method not implemented.");
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function which will generate Parameters for the desired Function
|
|
|
|
* @param task The Taskobject.
|
|
|
|
*/
|
|
|
|
protected _generateParameters(task: IParseableTransitionDescription) {
|
|
|
|
// Only Adapt a Copy
|
2020-12-01 12:05:35 +00:00
|
|
|
const ret = deepClone(task.params);
|
2020-11-05 17:01:47 +00:00
|
|
|
const pair = new Map<string, string>();
|
|
|
|
|
|
|
|
// Adapt the Parameters.
|
|
|
|
for (const updateDefinition of task.dynamicParams) {
|
2020-12-01 12:05:35 +00:00
|
|
|
pair.set(updateDefinition.usedVariable, "\"" + updateDefinition.usedVariable + "\"");
|
2020-11-05 17:01:47 +00:00
|
|
|
rsetattr(
|
|
|
|
ret,
|
|
|
|
updateDefinition.parameterPointer,
|
|
|
|
updateDefinition.usedVariable
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-12-01 12:05:35 +00:00
|
|
|
const obj = JSON.stringify(ret, undefined, 4);
|
2020-11-05 17:01:47 +00:00
|
|
|
|
|
|
|
// Create The Text which will be used for the Parameters
|
|
|
|
for (const [key, value] of pair.entries()) {
|
|
|
|
replaceAll(obj, value, key);
|
|
|
|
}
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Array, containing all Elements which should be replaced.
|
|
|
|
protected _replace: {
|
|
|
|
regex: RegExp;
|
|
|
|
replacer: string;
|
|
|
|
}[] = [
|
|
|
|
{
|
|
|
|
regex: /(?<=[ \]\)])or(?=[ \[\(])/g,
|
|
|
|
replacer: "||"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /(?<=[ \]\)])and(?=[ \[\(])/g,
|
|
|
|
replacer: "&&"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /(?<=[ \]\)])sin(?=[ \[\(])/g,
|
|
|
|
replacer: "Math.sin"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /(?<=[ \]\)])cos(?=[ \[\(])/g,
|
|
|
|
replacer: "Math.cos"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// (?<=[ \]\)])
|
|
|
|
regex: /not(?=[ \[\(])/g,
|
|
|
|
replacer: "!"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /(?<=[ \]\)])\|(?=[ \[\(])/g,
|
|
|
|
replacer: "||"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
regex: /(?<=[ \]\)])\&(?=[ \[\(])/g,
|
|
|
|
replacer: "&&"
|
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function, which will be used to adapt the Path.
|
|
|
|
* @param value
|
|
|
|
*/
|
|
|
|
protected _adaptGuard(guard: string,
|
|
|
|
simplifiedGuard: string,
|
|
|
|
OriginalScope: {
|
|
|
|
[index: string]: {
|
|
|
|
source: string;
|
|
|
|
schema: IJsonSchema;
|
|
|
|
};
|
|
|
|
},
|
|
|
|
simplifiedScope: {
|
|
|
|
[index: string]: {
|
|
|
|
source: string;
|
|
|
|
schema: IJsonSchema;
|
|
|
|
};
|
|
|
|
},
|
|
|
|
mappingOriginalToSimplified: Map<string, string>,
|
|
|
|
mappingSimplifiedToOriginal: Map<string, string>,
|
|
|
|
mappingSimplifiedToAdapted: Map<string, string>,
|
|
|
|
mappingAdaptedToSimplified: Map<string, string>,
|
|
|
|
mappingVariableToRoot: Map<string, string>) {
|
|
|
|
let adaptedGuard = simplifiedGuard;
|
|
|
|
|
|
|
|
// Firstly get rid off the Elements (Chars, ot replace in the Equation)
|
|
|
|
for (const data of this._replace) {
|
|
|
|
adaptedGuard = adaptedGuard.replace(data.regex, data.replacer);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Adapt the used Names
|
|
|
|
for (const [simple, adapted] of mappingSimplifiedToAdapted) {
|
|
|
|
adaptedGuard = replaceAll(adaptedGuard, simple, adapted);
|
|
|
|
}
|
|
|
|
|
|
|
|
return adaptedGuard;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function, which will be used to adapt a Variable Name.
|
|
|
|
* @param value The original Variable Name
|
|
|
|
*/
|
|
|
|
protected _adaptVariableName(
|
|
|
|
variable: string,
|
|
|
|
simplifiedName: string,
|
|
|
|
path: string
|
|
|
|
) {
|
|
|
|
return "vars['" + simplifiedName + "']";
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function, which will be used to generate Function Code.
|
|
|
|
* @param taskData
|
|
|
|
*/
|
|
|
|
protected _getFunctionTriggerCode(_taskData: IParseableTransitionDescription) {
|
|
|
|
|
|
|
|
const taskData = deepClone(_taskData);
|
|
|
|
taskData.params = this._generateParameters(taskData);
|
|
|
|
|
|
|
|
const updateTaskResult =
|
2020-12-01 12:05:35 +00:00
|
|
|
"" +
|
2020-11-05 17:01:47 +00:00
|
|
|
`
|
|
|
|
_memoryInterface.set('{{id}}.function.output', {
|
|
|
|
done: false,
|
|
|
|
error: false,
|
|
|
|
result: null,
|
|
|
|
errorObject: null
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
_broker.performTask('{{functionName}}', {{{params}}}, '{{id}}', 'async', (error, parameters, result) => {
|
|
|
|
_memoryInterface.set('{{id}}.function.output', {
|
|
|
|
result: result,
|
|
|
|
done: error ? false : true,
|
|
|
|
error: error ? true : false,
|
|
|
|
errorObject: error
|
|
|
|
});
|
|
|
|
});
|
|
|
|
`;
|
|
|
|
|
|
|
|
const render = handlebars.compile(updateTaskResult);
|
|
|
|
return render(taskData);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected _convertInput(definition: {
|
|
|
|
// Amount of Tokens that will be consumed (Result must be greater the minTokens)
|
|
|
|
consumed: IArcExpression;
|
|
|
|
placeId: string;
|
|
|
|
type:
|
|
|
|
| "expression"
|
|
|
|
| "inhibitor"
|
|
|
|
| "multiexpression"
|
|
|
|
| "test"
|
|
|
|
| "value"
|
|
|
|
| "variable";
|
|
|
|
minTokens: number;
|
|
|
|
}) {
|
|
|
|
return {
|
|
|
|
placeId: definition.placeId,
|
|
|
|
minTokens: definition.minTokens,
|
|
|
|
tokensToRemove: 1,
|
2020-12-01 12:05:35 +00:00
|
|
|
};
|
2020-11-05 17:01:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected _convertOutput(definition: {
|
|
|
|
// Amount of Tokens that will be produced
|
|
|
|
produced: IArcExpression;
|
|
|
|
placeId: string;
|
|
|
|
type:
|
|
|
|
| "expression"
|
|
|
|
| "inhibitor"
|
|
|
|
| "multiexpression"
|
|
|
|
| "test"
|
|
|
|
| "value"
|
|
|
|
| "variable";
|
|
|
|
maxTokens: number;
|
|
|
|
}): {
|
|
|
|
// Amount of Tokens that will be produced
|
|
|
|
placeId: string;
|
|
|
|
maxTokens: number;
|
|
|
|
tokensToAdd: number;
|
|
|
|
} {
|
|
|
|
return {
|
|
|
|
placeId: definition.placeId,
|
|
|
|
maxTokens: definition.maxTokens,
|
|
|
|
tokensToAdd: 1,
|
2020-12-01 12:05:35 +00:00
|
|
|
};
|
2020-11-05 17:01:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected _templates: {
|
|
|
|
[index: string]: string;
|
|
|
|
} = {
|
2020-12-01 12:05:35 +00:00
|
|
|
ifHeaderTemplate: "{{#unless isFirst}}else {{/unless}}if ({{> testPrePlaces}}{{> testPostPlaces}}{{> testGuard}}) {",
|
|
|
|
testPrePlaces: "{{#each inputs}} ((tokens['{{placeId}}']{{#if minTokens}} - {{minTokens}}{{/if}}) >= {{tokensToRemove}}) &&{{/each}}",
|
|
|
|
testPostPlaces: "{{#each testOutputs}} ((tokens['{{placeId}}'] + {{tokensToAdd}}) <= {{maxTokens}}) &&{{/each}}",
|
|
|
|
testGuard: " {{{ externalGuard }}}",
|
|
|
|
removeTokens: "{{#each inputs}}tokens['{{placeId}}'] -= {{tokensToRemove}};{{/each}}",
|
|
|
|
addTokens: "{{#each outputs}}tokens['{{placeId}}'] += {{tokensToAdd}};{{/each}}",
|
2020-11-05 17:01:47 +00:00
|
|
|
mainTemplate:
|
2020-12-01 12:05:35 +00:00
|
|
|
"" +
|
2020-11-05 17:01:47 +00:00
|
|
|
`
|
|
|
|
import { ZISSLogger, DEFAULT_LOGGER } from '../modules/ZISS-Logger/src/Unique.Logger';
|
|
|
|
const _logger = ZISSLogger.logger.getLogger();
|
|
|
|
/** Add Console Logger. */
|
|
|
|
ZISSLogger.logger.addStream(DEFAULT_LOGGER);
|
|
|
|
|
|
|
|
_logger.info('started');
|
|
|
|
|
|
|
|
import 'reflect-metadata';
|
|
|
|
|
|
|
|
import * as BROKERFILEBASE from '../modules/ZISS-Broker/assembly/manual-assembly';
|
|
|
|
import * as BROKER from '../modules/ZISS-Broker/assembly/manual-assembly';
|
|
|
|
import * as MEMORYINTERFACE from '../modules/ZISS-Memory-Interface/assembly/manual-assembly';
|
|
|
|
import * as PUBSUB from '../modules/ZISS-Publish-And-Subscribe-System/assembly/manual-assembly';
|
|
|
|
|
|
|
|
import { Builder } from '../modules/ZISS-Assembly-Builder/src/Container-Builder.FileLoader';
|
|
|
|
|
|
|
|
import { ArgumentParser } from 'argparse';
|
|
|
|
|
|
|
|
const parser = new ArgumentParser({
|
|
|
|
version: '1.0.0',
|
|
|
|
addHelp: true,
|
|
|
|
description: 'Main Starter For the Kernel Tool'
|
|
|
|
});
|
|
|
|
|
|
|
|
parser.addArgument(
|
|
|
|
['-l', '--level'],
|
|
|
|
{
|
|
|
|
help: 'The Loglevel. Defaults to Debug',
|
|
|
|
defaultValue: 'info',
|
|
|
|
choices: ['debug', 'error', 'fatal', 'info', 'trace', 'warn'],
|
|
|
|
dest: 'level',
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
const args = parser.parseArgs();
|
|
|
|
|
|
|
|
ZISSLogger.logger.level = args.level;
|
|
|
|
|
|
|
|
Builder.load();
|
|
|
|
|
|
|
|
Builder.on('loaded', () => {
|
|
|
|
|
|
|
|
const _loader = Builder.instance.container.get<BROKERFILEBASE.FilebasedBroker>(BROKERFILEBASE.TYPES.BrokerFilebased);
|
|
|
|
const _broker = Builder.instance.container.get<BROKER.Broker>(BROKER.TYPES.Broker);
|
|
|
|
const _memoryInterface = Builder.instance.container.get<MEMORYINTERFACE.BaseStorage>(MEMORYINTERFACE.TYPES.Storage);
|
|
|
|
const _pubSub = Builder.instance.container.get<PUBSUB.PubSubSystem>(PUBSUB.TYPES.PubSubSystem);
|
|
|
|
|
|
|
|
|
|
|
|
const vars: {[index:string]:any} = {
|
|
|
|
'true':true
|
|
|
|
};
|
|
|
|
|
|
|
|
const tokens: {[index:string]:number} = {
|
|
|
|
{{#each places}}
|
|
|
|
'{{id}}' : {{tokens.length}},
|
|
|
|
{{/each}}
|
|
|
|
};
|
|
|
|
|
|
|
|
function mainLoop(){
|
|
|
|
let checkTransitions = true;
|
|
|
|
|
|
|
|
// Main Loop, which will iterate, until no action is left.
|
|
|
|
while (checkTransitions) {
|
|
|
|
|
|
|
|
checkTransitions = false;
|
|
|
|
|
|
|
|
{{#each transitions}}
|
|
|
|
// Test Transtion {{{label}}}
|
|
|
|
{{> ifHeaderTemplate}}
|
|
|
|
{{#if inputs}}
|
|
|
|
|
|
|
|
// Removing Tokens from Pre-Places.
|
|
|
|
{{> removeTokens}}
|
|
|
|
{{/if}}
|
|
|
|
{{#if outputs}}
|
|
|
|
|
|
|
|
// Adding Tokens to the Post-Places.
|
|
|
|
{{> addTokens}}
|
|
|
|
{{/if}}
|
|
|
|
{{#if functionName}}
|
|
|
|
|
|
|
|
// Execute the desired Function
|
|
|
|
{{#getFunctionCode this}}{{/getFunctionCode}}
|
|
|
|
{{/if}}
|
|
|
|
|
|
|
|
|
|
|
|
// Make shure the System Loops over again.
|
|
|
|
checkTransitions = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
{{/each}}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Define the Variables
|
|
|
|
|
|
|
|
{{#each subscribedVariables}}
|
|
|
|
Object.defineProperty(vars, '{{simplifiedName}}', {
|
|
|
|
get: () => _memoryInterface.get('{{path}}'),
|
|
|
|
set: (value) => _memoryInterface.set('{{path}}', value),
|
|
|
|
enumerable: true
|
|
|
|
});
|
|
|
|
|
|
|
|
_pubSub.createSubscription('{{path}}', (data) => {
|
|
|
|
mainLoop();
|
|
|
|
});
|
|
|
|
{{/each}}
|
|
|
|
|
|
|
|
{{#each variables}}
|
|
|
|
{{#if hasValue}}
|
|
|
|
_memoryInterface.set('{{path}}', {{data}});
|
|
|
|
{{/if}}
|
|
|
|
{{/each}}
|
|
|
|
|
|
|
|
const _func = async function () {
|
|
|
|
try {
|
|
|
|
await _loader.loadModules();
|
|
|
|
// Perform autostart
|
|
|
|
await _loader.performAutostartConfig();
|
|
|
|
|
|
|
|
ZISSLogger.logger.level = args.level;
|
|
|
|
ZISSLogger.logger.setLoglevel('delimiter', 'info');
|
|
|
|
ZISSLogger.logger.setLoglevel('logic.functions', 'info');
|
|
|
|
|
|
|
|
// Start the Task
|
|
|
|
mainLoop();
|
|
|
|
} catch (e) {
|
|
|
|
_logger.error(e, 'Error during Loading the Content');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
_func();
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
`
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Function, which will generate the MainLoop.
|
|
|
|
* @param network
|
|
|
|
*/
|
|
|
|
mainLoop(network: ILogicNetwork): string {
|
|
|
|
// Reference to the Own Object.
|
|
|
|
const _this = this;
|
|
|
|
|
|
|
|
handlebars.registerHelper("getFunctionCode", (taskData) =>
|
|
|
|
_this._getFunctionTriggerCode(taskData)
|
|
|
|
);
|
|
|
|
|
|
|
|
this.linkTemplates();
|
|
|
|
|
|
|
|
const render = handlebars.compile(this._templates.mainTemplate);
|
|
|
|
|
2020-12-01 12:05:35 +00:00
|
|
|
return render(this.getParseableLogic(network));
|
2020-11-05 17:01:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
instanceCreation(context: IParsedLogic): string {
|
|
|
|
throw new Error("Method not implemented.");
|
|
|
|
}
|
|
|
|
}
|