exporttoppdevs.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. const {
  2. __errorContinuable,
  3. __httpReq,
  4. __wHttpReq,
  5. __postInternalErrorMsg, __postMessage,
  6. __sequenceNumber,
  7. __successContinuable,
  8. __uri_to_id
  9. } = require("../__worker");
  10. const _do = require("../___do");
  11. const _utils = require('../utils');
  12. const _fs = _do.convert(require('fs'), ['readFile', 'writeFile', 'readdir']);
  13. const _fspp = _do.convert(require('../___fs++'), ['mkdirs']);
  14. module.exports = {
  15. 'interfaces': [{'method':'POST', 'url=':'/exportmtoppdevs'}],
  16. 'csworker':
  17. function(resp, method, uri, reqData, wcontext) {
  18. var actions = [__wHttpReq('GET', '/current.model?wid=' + wcontext.__aswid)];
  19. _do.chain(actions) (
  20. function(asdata) {
  21. var writeActions = [_fspp.mkdirs('./exported_to_pypdevs/')];
  22. _do.chain(writeActions) (
  23. function() {
  24. var file_contents = '',
  25. as = _utils.jsonp(asdata['data']),
  26. type_map = {},
  27. type_map_keys = {},
  28. incoming = {},
  29. outgoing = {};
  30. file_contents += 'import sys\n';
  31. file_contents += 'sys.path.append("../../pypdevs/src/")\n\n';
  32. file_contents += 'from DEVS import *\n';
  33. file_contents += 'from infinity import INFINITY\n';
  34. file_contents += 'from util import *\n\n';
  35. for (var key in as.nodes) {
  36. var node = as.nodes[key];
  37. if (!(node['$type'] in type_map)) {
  38. type_map[node['$type']] = [];
  39. type_map_keys[node['$type']] = [];
  40. }
  41. type_map[node['$type']].push(node);
  42. type_map_keys[node['$type']].push(key);
  43. node['$key'] = key;
  44. }
  45. function safe_add(l, el) {
  46. if (l.indexOf(el) == -1) {
  47. l.push(el);
  48. }
  49. }
  50. function calc_in_out_rel(rel_type) {
  51. for (var idx in type_map_keys[rel_type]) {
  52. key = type_map_keys[rel_type][idx];
  53. incoming[key] = [];
  54. outgoing[key] = [];
  55. for (var e_key in as.edges) {
  56. var e = as.edges[e_key];
  57. if (e['dest'] == key) {
  58. safe_add(incoming[key], e['src']);
  59. if (!(e['src'] in outgoing)) {
  60. outgoing[e['src']] = [];
  61. }
  62. safe_add(outgoing[e['src']], key);
  63. }
  64. if (e['src'] == key) {
  65. safe_add(outgoing[key], e['dest']);
  66. if (!(e['dest'] in incoming)) {
  67. incoming[e['dest']] = [];
  68. }
  69. safe_add(incoming[e['dest']], key);
  70. }
  71. }
  72. }
  73. }
  74. calc_in_out_rel('/Formalisms/ParallelDEVS/ParallelDEVS/states');
  75. calc_in_out_rel('/Formalisms/ParallelDEVS/ParallelDEVS/ports');
  76. calc_in_out_rel('/Formalisms/ParallelDEVS/ParallelDEVS/channel');
  77. calc_in_out_rel('/Formalisms/ParallelDEVS/ParallelDEVS/statedef');
  78. calc_in_out_rel('/Formalisms/ParallelDEVS/ParallelDEVS/submodels');
  79. calc_in_out_rel('/Formalisms/ParallelDEVS/ParallelDEVS/ExternalTransition');
  80. calc_in_out_rel('/Formalisms/ParallelDEVS/ParallelDEVS/InternalTransition');
  81. calc_in_out_rel('/Formalisms/ParallelDEVS/ParallelDEVS/ConfluentTransition');
  82. for (var key in type_map['/Formalisms/ParallelDEVS/ParallelDEVS/StateDefinition']) {
  83. var node = type_map['/Formalisms/ParallelDEVS/ParallelDEVS/StateDefinition'][key],
  84. list_of_params = ['name=""'].concat(node['parameters']['value'].map(function(el) {return el['name'] + '=None';})),
  85. list_of_param_names = ['name'].concat(node['parameters']['value'].map(function(el) {return el['name'];})),
  86. list_of_attrs = [['name', '']].concat(node['attributes']['value'].map(function(el) {return [el['name'], el['default']];}));
  87. file_contents += 'class ' + node['name']['value'] + ':\n';
  88. file_contents += '\tdef __init__(self, ' + list_of_params.join(', ') + '):\n';
  89. file_contents += list_of_attrs.map(function(el) {return '\t\tself.' + el[0] + ' = ' + (list_of_param_names.indexOf(el[0]) != -1 ? el[0] : el[1]);}).join('\n') + "\n";
  90. file_contents += node['__init__']['value'].split('\n').map(function(line) {return '\t\t' + line;}).join('\n');
  91. file_contents += '\n\n';
  92. }
  93. for (var key in type_map['/Formalisms/ParallelDEVS/ParallelDEVS/Event']) {
  94. var node = type_map['/Formalisms/ParallelDEVS/ParallelDEVS/Event'][key],
  95. list_of_params = (node['parameters']['value'].map(function(el) {return el['name'] + '=None';})),
  96. list_of_param_names = (node['parameters']['value'].map(function(el) {return el['name'];})),
  97. list_of_attrs = (node['attributes']['value'].map(function(el) {return [el['name'], el['default']];}));
  98. file_contents += 'class ' + node['name']['value'] + ':\n';
  99. file_contents += '\tdef __init__(self, ' + list_of_params.join(', ') + '):\n';
  100. file_contents += list_of_attrs.map(function(el) {return '\t\tself.' + el[0] + ' = ' + (list_of_param_names.indexOf(el[0]) != -1 ? el[0] : el[1]);}).join('\n') + "\n";
  101. file_contents += node['__init__']['value'].split('\n').map(function(line) {return '\t\t' + line;}).join('\n');
  102. file_contents += '\n\n';
  103. file_contents += '\tdef __str__(self):\n';
  104. file_contents += '\t\treturn "' + node['name']['value'] + '(" + ' + list_of_attrs.map(function(el) {return 'str(self.' + el[0] + ')';}).join(' + ", " + ') + ' + ")"';
  105. file_contents += '\n\n';
  106. }
  107. for (var idx in type_map['/Formalisms/ParallelDEVS/ParallelDEVS/AtomicDEVS']) {
  108. var node = type_map['/Formalisms/ParallelDEVS/ParallelDEVS/AtomicDEVS'][idx],
  109. list_of_params = (node['parameters']['value'].map(function(el) {return el['name'] + '=None';})),
  110. list_of_param_names = (node['parameters']['value'].map(function(el) {return el['name'];})),
  111. list_of_attrs = (node['attributes']['value'].map(function(el) {return [el['name'], el['default']];}));
  112. file_contents += 'class ' + node['name']['value'] + '(AtomicDEVS):\n';
  113. file_contents += '\tdef __init__(' + (['self', 'name="' + node['name']['value'] + '"'].concat(list_of_params).join(', ')) + '):\n';
  114. file_contents += '\t\tAtomicDEVS.__init__(self, name)\n';
  115. file_contents += list_of_attrs.map(function(el) {return '\t\tself.' + el[0] + ' = ' + (list_of_param_names.indexOf(el[0]) != -1 ? el[0] + ' if ' + el[0] + ' is not None else ' + el[1] : el[1]);}).join('\n');
  116. file_contents += '\n';
  117. key = type_map_keys['/Formalisms/ParallelDEVS/ParallelDEVS/AtomicDEVS'][idx];
  118. statedef = as.nodes[outgoing[outgoing[key].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/statedef';})[0]][0]];
  119. states = outgoing[key].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/states';}).map(function(statesid) {return outgoing[statesid][0];}).map(function(sid) {return as.nodes[sid];});
  120. defstate = states.filter(function(el) {return el['initial']['value'];})[0];
  121. list_of_assigns = ['name="' + defstate['name']['value'] + '"'].concat(statedef['initial_binding']['value'].map(function(el) {return el['name'] + '=' + el['val'];}));
  122. file_contents += '\t\tself.state = ' + statedef['name']['value'] + '(' + list_of_assigns.join(', ') + ')\n';
  123. file_contents += node['__init__']['value'].split('\n').map(function(line) {return '\t\t' + line;}).join('\n') + "\n";
  124. ports = outgoing[key].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/ports';}).map(function(portsid) {return outgoing[portsid][0];}).map(function(pid) {return as.nodes[pid];});
  125. file_contents += '\t\tself.my_ports = {' + ports.map(function(el) {return '"' + el['name']['value'] + '": ' + (el['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/OutputPort' ? 'self.addOutPort("' : 'self.addInPort("') + el['name']['value'] + '")';}).join(', ') + '}\n\n';
  126. file_contents += '\tdef timeAdvance(self):\n';
  127. file_contents += states.map(function(s) {return '\t\tif self.state.name == "' + s['name']['value'] + '":\n' + s['time_advance']['value'].split('\n').map(function(line) {return '\t\t\t' + line;}).join('\n');}).join('\n');
  128. file_contents += '\n\n';
  129. file_contents += '\tdef outputFnc(self):\n';
  130. file_contents += '\t\tdef subfunc(self):\n';
  131. file_contents += states.map(function(s) {return '\t\t\tif self.state.name == "' + s['name']['value'] + '":\n' + (s['output']['value'] == '' ? ['\t\t\t\treturn {}'] : s['output']['value'].split('\n').map(function(line) {return '\t\t\t\t' + line;}).join('\n'));}).join('\n') + "\n";
  132. file_contents += '\t\treturn {self.my_ports[k]: v for k, v in subfunc(self).iteritems()}\n';
  133. file_contents += '\n\n';
  134. file_contents += '\tdef intTransition(self):\n';
  135. var content = false;
  136. for (var sidx in states) {
  137. s = states[sidx];
  138. if (outgoing[s['$key']]) {
  139. internals = outgoing[s['$key']].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/InternalTransition';}).map(function(tid) {return as.nodes[tid];});
  140. for (var iidx in internals) {
  141. content = true;
  142. internal = internals[iidx];
  143. var target = as.nodes[outgoing[internal['$key']][0]],
  144. cond_name = 'cond_int_' + s['name']['value'] + '_to_' + target['name']['value'],
  145. action_name = 'action_int_' + s['name']['value'] + '_to_' + target['name']['value'];
  146. file_contents += '\t\t\def ' + cond_name + '():\n';
  147. file_contents += internal['condition']['value'] == '' ? '\t\t\treturn True' : internal['condition']['value'].split('\n').map(function(line) {return '\t\t\t' + line;}).join('\n');
  148. file_contents += '\n\t\t\def ' + action_name + '():\n';
  149. file_contents += internal['action']['value'] == '' ? '\t\t\treturn {}' : internal['action']['value'].split('\n').map(function(line) {return '\t\t\t' + line;}).join('\n');
  150. file_contents += '\n\t\tif self.state.name == "' + s['name']['value'] + '" and ' + cond_name + '():\n';
  151. file_contents += '\t\t\treturn ' + statedef['name']['value'] + '(name="' + target['name']['value'] + '", **' + action_name + '())\n\n';
  152. }
  153. }
  154. }
  155. if (!content) {
  156. file_contents += '\t\treturn AtomicDEVS.intTransition(self)\n';
  157. } else {
  158. file_contents += '\t\telse:\n';
  159. file_contents += '\t\t\treturn AtomicDEVS.intTransition(self)\n';
  160. }
  161. file_contents += '\n';
  162. file_contents += '\tdef extTransition(self, my_inputs):\n';
  163. file_contents += '\t\tinputs = {k.getPortName(): v for k, v in my_inputs.iteritems()}\n';
  164. content = false;
  165. for (var sidx in states) {
  166. s = states[sidx];
  167. if (outgoing[s['$key']]) {
  168. let externals = outgoing[s['$key']].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/ExternalTransition';}).map(function(tid) {return as.nodes[tid];});
  169. for (var iidx in externals) {
  170. content = true;
  171. let extern = externals[iidx];
  172. var target = as.nodes[outgoing[extern['$key']][0]],
  173. cond_name = 'cond_ext_' + s['name']['value'] + '_to_' + target['name']['value'],
  174. action_name = 'action_ext_' + s['name']['value'] + '_to_' + target['name']['value'];
  175. file_contents += '\t\t\def ' + cond_name + '():\n';
  176. file_contents += extern['condition']['value'] == '' ? '\t\t\treturn True' : extern['condition']['value'].split('\n').map(function(line) {return '\t\t\t' + line;}).join('\n');
  177. file_contents += '\n\t\t\def ' + action_name + '():\n';
  178. file_contents += extern['action']['value'] == '' ? '\t\t\treturn {}' : extern['action']['value'].split('\n').map(function(line) {return '\t\t\t' + line;}).join('\n');
  179. file_contents += '\n\t\tif self.state.name == "' + s['name']['value'] + '" and ' + cond_name + '():\n';
  180. file_contents += '\t\t\treturn ' + statedef['name']['value'] + '(name="' + target['name']['value'] + '", **' + action_name + '())\n\n';
  181. }
  182. }
  183. }
  184. if (!content) {
  185. file_contents += '\t\treturn AtomicDEVS.extTransition(self, my_inputs)\n';
  186. } else {
  187. file_contents += '\t\telse:\n';
  188. file_contents += '\t\t\treturn AtomicDEVS.extTransition(self, my_inputs)\n';
  189. }
  190. file_contents += '\n';
  191. file_contents += '\tdef confTransition(self, my_inputs):\n';
  192. file_contents += '\t\tinputs = {k.getPortName(): v for k, v in my_inputs.iteritems()}\n';
  193. content = false;
  194. for (var sidx in states) {
  195. s = states[sidx];
  196. confluents = outgoing[s['$key']].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/ConfluentTransition';}).map(function(tid) {return as.nodes[tid];});
  197. for (var iidx in confluents) {
  198. content = true;
  199. confluent = confluents[iidx];
  200. var target = as.nodes[outgoing[confluent['$key']][0]],
  201. cond_name = 'cond_conf_' + s['name']['value'] + '_to_' + target['name']['value'],
  202. action_name = 'action_conf_' + s['name']['value'] + '_to_' + target['name']['value'];
  203. file_contents += '\t\t\def ' + cond_name + '():\n';
  204. file_contents += confluent['condition']['value'] == '' ? '\t\t\treturn True' : confluent['condition']['value'].split('\n').map(function(line) {return '\t\t\t' + line;}).join('\n');
  205. file_contents += '\n\t\t\def ' + action_name + '():\n';
  206. file_contents += confluent['action']['value'] == '' ? '\t\t\treturn {}' : confluent['action']['value'].split('\n').map(function(line) {return '\t\t\t' + line;}).join('\n');
  207. file_contents += '\n\t\tif self.state.name == "' + s['name']['value'] + '" and ' + cond_name + '():\n';
  208. file_contents += '\t\t\treturn ' + statedef['name']['value'] + '(name="' + target['name']['value'] + '", **' + action_name + '())\n\n';
  209. }
  210. }
  211. if (!content) {
  212. file_contents += '\t\treturn AtomicDEVS.confTransition(self, my_inputs)\n';
  213. } else {
  214. file_contents += '\t\telse:\n';
  215. file_contents += '\t\t\treturn AtomicDEVS.confTransition(self, my_inputs)\n';
  216. }
  217. file_contents += '\n';
  218. }
  219. for (var idx in type_map['/Formalisms/ParallelDEVS/ParallelDEVS/CoupledDEVS']) {
  220. var node = type_map['/Formalisms/ParallelDEVS/ParallelDEVS/CoupledDEVS'][idx],
  221. list_of_params = (node['parameters']['value'].map(function(el) {return el['name'] + '=None';})),
  222. list_of_param_names = (node['parameters']['value'].map(function(el) {return el['name'];})),
  223. list_of_attrs = (node['attributes']['value'].map(function(el) {return [el['name'], el['default']];}));
  224. file_contents += 'class ' + node['name']['value'] + '(CoupledDEVS):\n';
  225. file_contents += '\tdef __init__(' + (['self', 'name="' + node['name']['value'] + '"'].concat(list_of_params).join(', ')) + '):\n';
  226. file_contents += '\t\tCoupledDEVS.__init__(self, name)\n';
  227. file_contents += list_of_attrs.map(function(el) {return '\t\tself.' + el[0] + ' = ' + (list_of_param_names.indexOf(el[0]) != -1 ? el[0] : el[1]);}).join('\n') + "\n";
  228. file_contents += node['__init__']['value'].split('\n').map(function(line) {return '\t\t' + line;}).join('\n') + "\n";
  229. key = type_map_keys['/Formalisms/ParallelDEVS/ParallelDEVS/CoupledDEVS'][idx];
  230. ports = outgoing[key].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/ports';}).map(function(portsid) {return outgoing[portsid][0];}).map(function(pid) {return as.nodes[pid];});
  231. file_contents += '\t\tself.my_ports = {' + ports.map(function(el) {return '"' + el['name']['value'] + '": ' + (el['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/OutputPort' ? 'self.addOutPort("' : 'self.addInPort("') + el['name']['value'] + '")';}).join(', ') + '}\n';
  232. file_contents += '\t\tself.submodels = {}\n';
  233. submodels = outgoing[key].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/submodels';}).map(function(submodelsid) {return outgoing[submodelsid][0];}).map(function(mid) {return as.nodes[mid];});
  234. file_contents += submodels.map(function(m) {return '\t\tself.submodels["' + m['name']['value'] + '"] = self.addSubModel(' + m['devs_type']['value'] + '(' + ['name="' + m['name']['value'] + '"'].concat(m['parameter_binding']['value'].map(function(pb) {return pb['name'] + '=' + pb['val'];})).join(', ') + '))';}).join('\n');
  235. file_contents += '\n\n';
  236. myportkeys = ports.map(function(port) {return port['$key'];});
  237. port_to_m = {};
  238. m_to_ports = {};
  239. m_to_ports[key] = ports;
  240. ports.forEach(function(p) {port_to_m[p['$key']] = node;});
  241. for (var skey in submodels) {
  242. var m = submodels[skey];
  243. m_to_ports[m['$key']] = [];
  244. ports = outgoing[m['$key']].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/ports';}).map(function(portsid) {return outgoing[portsid][0];}).map(function(pid) {return as.nodes[pid];});
  245. ports.forEach(function(p) {port_to_m[p['$key']] = m; m_to_ports[m['$key']].push(p);});
  246. }
  247. for (var mkey in m_to_ports) {
  248. for (var pidx in m_to_ports[mkey]) {
  249. var p = m_to_ports[mkey][pidx],
  250. pkey = p['$key'];
  251. if (pkey in outgoing) {
  252. var conns = outgoing[pkey].filter(function(el) {return as.nodes[el]['$type'] == '/Formalisms/ParallelDEVS/ParallelDEVS/channel';}).map(function(channelid) {return as.nodes[channelid];});
  253. for (var cidx in conns) {
  254. var conn = conns[cidx],
  255. target = as.nodes[outgoing[conn['$key']][0]],
  256. transfname = 'transfer_' + as.nodes[mkey]['name']['value'] + '_' + as.nodes[pkey]['name']['value'] + '_to_' + target['name']['value'],
  257. fromportstr = (mkey == key ? 'self' : 'self.submodels["' + as.nodes[mkey]['name']['value'] + '"]') + '.my_ports["' + as.nodes[pkey]['name']['value'] + '"]',
  258. toportstr = (port_to_m[target['$key']]['$key'] == key ? 'self' : 'self.submodels["' + port_to_m[target['$key']]['name']['value'] + '"]') + '.my_ports["' + target['name']['value'] + '"]';
  259. if (conn['transfer_function']['value'] != '') {
  260. file_contents += '\t\tdef ' + transfname + '(event):\n';
  261. file_contents += conn['transfer_function']['value'].split('\n').map(function(line) {return '\t\t\t' + line;}).join('\n');
  262. file_contents += '\n\n';
  263. file_contents += '\t\tself.connectPorts(' + fromportstr + ', ' + toportstr + ', ' + transfname + ')\n\n';
  264. } else {
  265. file_contents += '\t\tself.connectPorts(' + fromportstr + ', ' + toportstr + ')\n';
  266. }
  267. }
  268. }
  269. }
  270. }
  271. file_contents += '\n';
  272. }
  273. _fs.writeFileSync('./exported_to_pypdevs/model.py', file_contents);
  274. file_contents = 'import sys\n';
  275. file_contents += 'sys.path.append("../../pypdevs/src/")\n\n';
  276. file_contents += 'from DEVS import *\n';
  277. file_contents += 'from model import *\n';
  278. file_contents += 'from python_runtime.statecharts_core import Event\n';
  279. file_contents += 'from sccd import Controller\n\n';
  280. file_contents += 'def termination_condition(time, model, transitioned):\n';
  281. file_contents += '\ttime = time[0]\n';
  282. file_contents += type_map['/Formalisms/ParallelDEVS/ParallelDEVS/Simulation'][0]['end_condition']['value'].split('\n').map(function(line) {return '\t' + line;}).join('\n') + '\n';
  283. _fs.writeFileSync('./exported_to_pypdevs/experiment.py', file_contents);
  284. __postMessage({'statusCode': 200,
  285. 'respIndex': resp});
  286. },
  287. function(writeErr) {__postInternalErrorMsg(resp, writeErr);}
  288. );
  289. },
  290. function(err) {__postInternalErrorMsg(resp, err);}
  291. );
  292. },
  293. 'asworker':
  294. function(resp, method, uri, reqData, wcontext)
  295. {
  296. __postMessage(
  297. {'statusCode': 200,
  298. 'respIndex': resp});
  299. }
  300. };