diff --git a/app.js b/app.js index 437bd19fe27ca8df1e8778a0e5afe9d571519e02..b56d788dfb67e8597eb7559f9c21dfb2dfe68034 100644 --- a/app.js +++ b/app.js @@ -86,7 +86,8 @@ ipc.config.silent = true; ipc.serve(() => ipc.server.on('rundynarematlab', (data, socket) => { global.mysocket=socket; console.log('received ipc message from router'); - mymessage={'messageid': 'rundynarematlab'}; + console.log(data) + mymessage={'messageid': 'rundynarematlab','messagetype': data}; child.send(mymessage); }) @@ -120,6 +121,11 @@ child.on('message', message => { } + if (message.message==2){ + console.log('-=perfect foresight computation completed=-'); + finishperfect(); + } + } if (message.messageid=='stdoutmessage'){ @@ -153,7 +159,7 @@ async function finishstochastic() { try { stomatlabdata = await loadjsonfile('stochsimout.JSON'); } catch (error) { - return popthis('Error', 'Unable to open stochsimout.JSON to process:' + error); + return console.log('Unable to open stochsimout.JSON to process:' + error); } sockIO.emit('stochasticsimfinish', stomatlabdata); @@ -164,6 +170,23 @@ async function finishstochastic() { } +async function finishperfect() { + + // loading JSON output from Matlab + try { + permatlabdata = await loadjsonfile('perforout.JSON'); + } catch (error) { + return console.log('Unable to open perforout.JSON to process:' + error); + } + + sockIO.emit('perfectsimfinish', permatlabdata); + + console.log(permatlabdata); + + return false; + +} + diff --git a/appModules.js b/appModules.js index 3e1654de0eb2eb918b9301acf4fe4e786c2a4148..05a9b1047adcb282c7ddf0545ace3c4e6bdab4ad 100644 --- a/appModules.js +++ b/appModules.js @@ -812,6 +812,7 @@ module.exports = { // removing old JSON files and writing the correct file if (runtype == 1) { + //writes JSON file for perfect foresight try { await module.exports.removeoldfile('perforout.JSON'); } catch (error) { @@ -839,6 +840,7 @@ module.exports = { } if (runtype == 2) { + //writes JSON file for stochastic simulations try { await module.exports.removeoldfile('stochsimout.JSON'); } catch (error) { diff --git a/background.js b/background.js index 9deef193ac71a96619f4ccfb22a48895fc761103..99b45734b5f40d95e749edc724d5c855da777ee4 100644 --- a/background.js +++ b/background.js @@ -47,13 +47,22 @@ async function main() { 'messageid': 'matlabready', 'message': 0 }; - } else { + } + if (origincalltype == 1) { + //this is the return from a stochastic simulation mymessage = { 'messageid': 'matlabready', 'message': 1 }; - // origincalltype = 0; } + if (origincalltype == 2) { + //this is the return from a perfect foresight computation + mymessage = { + 'messageid': 'matlabready', + 'message': 2 + }; + } + // process.send('matlabready', origincalltype); process.send(mymessage); // } @@ -82,14 +91,25 @@ async function main() { process.on('message', (pmessage) => { // var messageprocess=0; + + if (pmessage.messageid == 'rundynarematlab') { - // child.stdin.write('15+15\n'); - origincalltype = 1; - child.stdin.write('run temp.m;run di_stochastic_simulations.m;\n'); - // child.stdin.write('15+15\n'); - child.stdin.on('drain', () => {}); - // ready() - // messageprocess=1; + + + if (pmessage.messagetype=='stochastic'){ + origincalltype = 1; + child.stdin.write('run temp.m;run di_stochastic_simulations.m;\n'); + child.stdin.on('drain', () => {}); + } + + if (pmessage.messagetype=='perfect'){ + origincalltype = 2; + child.stdin.write('run temp.m;run di_perfect_foresight.m;\n'); + child.stdin.on('drain', () => {}); + } + + + } // mymessage={'messageid': 'stdoutmessage','message': 'received rundynarematlab in background' }; diff --git a/middleware/runpreprocess.js b/middleware/runpreprocess.js deleted file mode 100644 index 8b7558f7a46f4c0358602c3e12b76c845a3cb81f..0000000000000000000000000000000000000000 --- a/middleware/runpreprocess.js +++ /dev/null @@ -1,87 +0,0 @@ -const savetodb = require('../appModules').savetodb; -const removeoldfile = require('../appModules').removeoldfile; -const createnewfile = require('../appModules').createnewfile; -const preprocess = require('../appModules').preprocess; - - -module.exports = { - - // async function setpreprocess(modelcode) { - setpreprocess: (modelcode) => { - // will save and preprocess the model - - return new Promise(async function (resolve, reject) { - - var dynaremodel = ''; - // saving to database and retrieving the model from database - try { - dynaremodel = await savetodb(modelcode); - } catch (error) { - return reject({ - 'status': 200, - 'message': error.toString() - }); - } - - // removing old files - try { - await removeoldfile(dynaremodel['modelhash'] + '_ini_steady_state_model.json'); - } catch (error) { - return reject({ - 'status': 200, - 'message': error.toString() - }); - } - try { - await removeoldfile(dynaremodel['modelhash'] + '_ini.json'); - } catch (error) { - return reject({ - 'status': 200, - 'message': error.toString() - }); - } - try { - await removeoldfile(dynaremodel['modelhash'] + '_ini.mod'); - } catch (error) { - return reject({ - 'status': 200, - 'message': error.toString() - }); - } - - // creating a modfile from editor input. Flag 'w' truncates if file already exits - try { - await createnewfile(dynaremodel['modelhash'] + '_ini.mod', dynaremodel['modelcode']); - } catch (error) { - return reject({ - 'status': 200, - 'message': error.toString() - }); - } - - // calling dynare preprocessor on modfile - var dynarestdout = ''; - var preprocok = 1; - try { - dynarestdout += await preprocess(dynaremodel['modelhash'] + '_ini.mod', 3); - } catch (error) { - dynarestdout += error.toString(); - preprocok = 0; - } - - if (preprocok == 0) { - return reject({ - 'status': 100, - 'message': dynarestdout - }); - } else { - return resolve({ - 'status': 1, - 'message': dynarestdout - }); - } - - }); //end of main promise - } - -} diff --git a/middleware/runstochastic.js b/middleware/runprocesses.js similarity index 60% rename from middleware/runstochastic.js rename to middleware/runprocesses.js index 03e42e016313025e6fa02096fcd556eb9a3027e2..e0e077684f56f40d27f261b0fa0d2dc3438cec18 100644 --- a/middleware/runstochastic.js +++ b/middleware/runprocesses.js @@ -10,7 +10,85 @@ const ipc = require('node-ipc'); module.exports = { - setstochasticnode: (modelcode) => { + // async function setpreprocess(modelcode) { + setpreprocess: (modelcode) => { + // will save and preprocess the model + + return new Promise(async function (resolve, reject) { + + var dynaremodel = ''; + // saving to database and retrieving the model from database + try { + dynaremodel = await savetodb(modelcode); + } catch (error) { + return reject({ + 'status': 200, + 'message': error.toString() + }); + } + + // removing old files + try { + await removeoldfile(dynaremodel['modelhash'] + '_ini_steady_state_model.json'); + } catch (error) { + return reject({ + 'status': 200, + 'message': error.toString() + }); + } + try { + await removeoldfile(dynaremodel['modelhash'] + '_ini.json'); + } catch (error) { + return reject({ + 'status': 200, + 'message': error.toString() + }); + } + try { + await removeoldfile(dynaremodel['modelhash'] + '_ini.mod'); + } catch (error) { + return reject({ + 'status': 200, + 'message': error.toString() + }); + } + + // creating a modfile from editor input. Flag 'w' truncates if file already exits + try { + await createnewfile(dynaremodel['modelhash'] + '_ini.mod', dynaremodel['modelcode']); + } catch (error) { + return reject({ + 'status': 200, + 'message': error.toString() + }); + } + + // calling dynare preprocessor on modfile + var dynarestdout = ''; + var preprocok = 1; + try { + dynarestdout += await preprocess(dynaremodel['modelhash'] + '_ini.mod', 3); + } catch (error) { + dynarestdout += error.toString(); + preprocok = 0; + } + + if (preprocok == 0) { + return reject({ + 'status': 100, + 'message': dynarestdout + }); + } else { + return resolve({ + 'status': 1, + 'message': dynarestdout + }); + } + + }); //end of main promise + }, + + setpreprocessmore: (modelcode) => { // will save and run a stochastic simulation step return new Promise(async function (resolve, reject) { @@ -143,7 +221,6 @@ module.exports = { }); //end of main promise }, - runstochasticnode: (stosimval) => { return new Promise(async function (resolve, reject) { @@ -176,7 +253,79 @@ module.exports = { ipc.connectTo('appIPC', () => { ipc.of.appIPC.on('connect', () => { - ipc.of.appIPC.emit('rundynarematlab', "hello"); + ipc.of.appIPC.emit('rundynarematlab', "stochastic"); + ipc.disconnect('appIPC'); + }); + + // ipc.of.appIPC.on('message', (data) => { + // console.log('back in runstochastic') + // console.log(data); + // }); + + }); + + + + + + + + // this code will get the local user directory (do not erase until used) + // console.log(app.getPath('userData')); + + + + + // console.log('runstochasticnode last'); + return resolve('Done runstochasticnode !'); + + + }); //end of main promise + + + }, + + + runperfectnode: (perfectval) => { + + return new Promise(async function (resolve, reject) { + + + console.log('inside runperfectnode'); + + var modelhash = perfectval['modelhash']; + // preparing only the standardized JSON in data + var perfectindata = { + 'exonum': perfectval['exonum'], + 'simperiods': perfectval['simperiods'], + 'permanentshockexist': perfectval['permanentshockexist'], + 'transitoryshockexist': perfectval['transitoryshockexist'], + 'nonanticipatedshockexist': perfectval['nonanticipatedshockexist'], + 'delayexist': perfectval['delayexist'], + 'permanentshocksdescription': perfectval['permanentshocksdescription'], + 'shocksdescription': perfectval['shocksdescription'], + 'nonanticipmatrix': perfectval['nonanticipmatrix'] + }; + + + try { + await preparejsonfiles(modelhash, 1, perfectval, perfectindata); + } catch (error) { + return reject(error); + } + + // const reply = ipc.sendSync('performMatlab', 111); + // cl(reply); + + console.log('before IPC') + + ipc.config.id = 'routerIPC'; + ipc.config.retry = 1500; + // ipc.config.silent = true; + + ipc.connectTo('appIPC', () => { + ipc.of.appIPC.on('connect', () => { + ipc.of.appIPC.emit('rundynarematlab', "perfect"); ipc.disconnect('appIPC'); }); @@ -200,12 +349,16 @@ module.exports = { // console.log('runstochasticnode last'); - return resolve('hello'); + return resolve('Done runperfectnode !'); }); //end of main promise + + + + } @@ -213,4 +366,7 @@ module.exports = { -} \ No newline at end of file + + + +} diff --git a/public/static/js/perfectforesight.js b/public/static/js/perfectforesight.js new file mode 100644 index 0000000000000000000000000000000000000000..3e5ad80bfc99420bb07e6ed497fd835c58e93c8f --- /dev/null +++ b/public/static/js/perfectforesight.js @@ -0,0 +1,943 @@ +var matlabdata; +var numshocks = []; +for (i = 0; i < 1000; i++) { + numshocks[i] = 0; +} + +//------------------------------------------------------------@@@button set perfect +$('#setperfect').click(function () { + + var modelname = $('#codename').val(); + if (modelname == null || modelname == "") { + $.alert({ + title: 'Project name is empty.', + content: 'Please choose a name for this project...', + }); + return false; + } + + + var modelcode = { + 'modelcode': window.editor_dynare.getValue(), + 'modelhash': $('#codehash').val(), + 'modelname': $('#codename').val(), + 'accesstype': 'setperfect' + }; + + console.log(modelcode) + + $.ajax({ + url: $(editorform).attr('action'), + headers: { + 'x-csrf-token': $('#_csrf').val() + }, + type: "POST", + data: modelcode, + success: function (resp) { + + if (resp.status == 200) { + console.log("200") + return popthis('Error', resp.message); + } else if (resp.status == 100) { + console.log("100") + showconsolealert(resp.message, 1); + console.log('console error'); + return false; + } + + showconsolealert(resp.message, 1); + + var currentdate = new Date(); + $('#classlist-form-messages').text('Last saved at: ' + currentdate); + + // sucess handling + + //if (((resp.data.status == 1) || (resp.data.status == 2)) || (resp.data.status == 201)) { + + //the model has exo shocks: we make a table + // if a steady state has not been provided if ask extra info on that + dynaremodel = resp.modeljson; + + // steady-state compute table + document.getElementById("perforssinittable").innerHTML = ""; + if (resp.status == 201) { + var extrassinfo = ""; + var extrasshelp = ""; + if (resp.extrassinfo !== null) { + extrassinfo = resp.extrassinfo; + extrasshelp = " (the last known steady-state info have been loaded below)" + } + var extrasstype = ""; + if (resp.extrasstype == 1) { + extrasstype = 'checked'; + } + + sscomputeeendo = ` + <h4>Steady state</h4> + <p style="color:#3399CC">You did not provide any way to compute the steady-state. Please specify a way to compute the steady-state` + extrasshelp + `.</p> + <div class="form-group no-margin"> <textarea class="form-control" id="perforSSblock" name="perforSSblock" placeholder="Steady-state equations;" rows="7">` + extrassinfo + `</textarea> </div> + <div class="form-group no-margin"><label><input type="checkbox" name="issteadystatelock" id="issteadystateblock"` + extrasstype + `/> Check if the above will compute the exact steady-state (will be interpreted as a <span style="font-style: italic;">steady_state_model</span> block). Leave unchecked if the above should be used as a starting point to compute the steady-state (will be interpreted as an <span style="font-style: italic;">initval</span> block).</label></div> + <input id="modelsteadystatestatus" name="modelsteadystatestatus" value="99" type="hidden"> + `; + } else if (resp.status == 2) { + sscomputeeendo = ` + <input id="modelsteadystatestatus" name="modelsteadystatestatus" value="55" type="hidden"> + `; + } else { + sscomputeeendo = ` + <input id="modelsteadystatestatus" name="modelsteadystatestatus" value="0" type="hidden"> + `; + } + document.getElementById("perforssinittable").innerHTML = sscomputeeendo; + document.getElementById("model_endonum").value = (dynaremodel.endogenous).length; + document.getElementById("model_exonum").value = (dynaremodel.exogenous).length; + $('#perforModal').modal('show'); + //} + + }, + error: function () { + console.log('there was a problem checking the fields'); + } + }); + return false; +}); + + + +//--------------------------------------------@@@button add sequence of shocks code +$('#addshock').click(function() { + var rowindex; + var xcond = 0; + var iter = 0; + while (xcond == 0) { + if (numshocks[iter] == 0) { + xcond = 1; + rowindex = iter; + numshocks[iter] = 1; + } + iter = iter + 1; + } + + + expectedshockstable = ''; + expectedshockstable += '<tr><td><select id="shockname' + rowindex + '" class="form-control input-sm" name="shocks">'; + for (x in dynaremodel.exogenous) { + expectedshockstable += '<option value="' + x + '">' + dynaremodel.exogenous[x]["longName"] + '</option>'; + } + expectedshockstable += "</select></td>"; + expectedshockstable += '<td><input type="text" class="form-control no-border input-sm" name="shockstart' + rowindex + '" id="shockstart' + rowindex + '" placeholder="Start"></td>'; + expectedshockstable += '<td><input type="text" class="form-control no-border input-sm" name="shockend' + rowindex + '" id="shockend' + rowindex + '" placeholder="End"></td>'; + expectedshockstable += '<td><input type="text" class="form-control no-border input-sm" name="shockvalues' + rowindex + '" id="shockvalues' + rowindex + '" placeholder="Value(s)"></td>'; + expectedshockstable += '<td><input type="text" class="form-control no-border input-sm" name="shockanticipdate' + rowindex + '" id="shockanticipdate' + rowindex + '" placeholder="0"></td>'; + expectedshockstable += '<td><input type="checkbox" class="form-control no-border input-sm" name="shockanticip' + rowindex + '" id="shockanticip' + rowindex + '"></td>'; + expectedshockstable += '<td><input type="checkbox" class="form-control no-border input-sm" onclick="activateunactivateperiod(' + rowindex + ')" name="shockpermanent' + rowindex + '" id="shockpermanent' + rowindex + '"></td>'; + expectedshockstable += '<td><input type="button" value="X" onclick="SomeDeleteRowFunction(this,' + rowindex + ')" class="form-control no-border input-sm" name="removeshock' + rowindex + '" id="removeshock' + rowindex + '"></td></tr>'; + + $('#perforseqexptable tbody').append(expectedshockstable); + + return false; +}); + +//----------------------------------------------------@@@disable/unable periods when permanent shock is clicked +function activateunactivateperiod(thisnum) { + + if ($('#shockend' + thisnum.toString()).is(':disabled')) { + //textbox is disabled + $('#shockend' + thisnum.toString()).removeAttr('disabled'); + $('#shockstart' + thisnum.toString()).val(''); + } else { + $('#shockend' + thisnum.toString()).attr({ + 'disabled': 'disabled' + }); + $('#shockend' + thisnum.toString()).val(''); + $('#shockstart' + thisnum.toString()).val('1'); + } +} + +//----------------------------------------------------@@@removes a shock line in Shocks table +function SomeDeleteRowFunction(o, rowindex) { + var p = o.parentNode.parentNode; + p.parentNode.removeChild(p); + numshocks[rowindex] = 0; +} + + +//----------------------------------------------------@@@button run perfect: verifies input then runs perfect foresight simulation +$('#runperfect').click(function() { + //getting all the necessary info from the forms + var endonum = $('#model_endonum').val(); + var exonum = $('#model_exonum').val(); + var simperiods = $('#simperiods').val(); + var ssstatus = $('#modelsteadystatestatus').val(); + var globalvaluescount = 0; + // checking the shocks tab + var shockindex; + var shockvaluearray = []; + var shocksdescription = []; + var permanentshocksdescription = []; + var ssdescription = []; + var permanentshockexist = 0; + var nonanticipatedshockexist = 0; + var transitoryshockexist = 0; + var delayexist = 0; + var permanentflag = []; + var transitoryflag = []; + var shocksflag = []; + var nonanticipmatrix = []; + var trackrow = 0; + var sstype = 0; + + var ispermanent; + var isnonanticipated; + var isdelayed; + + for (i = 0; i < exonum; i++) { + permanentflag[i] = 0; + shocksflag[i] = 0; + transitoryflag[i] = 0; + } + + // setup tab checks + + // simulation periods check + if (simperiods == null || simperiods == "") { + $('.nav-tabs a[href="#perforsetuptable"]').tab('show'); + popthis('Setup error.', 'You did not specify the number of simulation periods.'); + return (0); + } else { + if (!(Number.isInteger(Number(simperiods)))) { + $('.nav-tabs a[href="#perforsetuptable"]').tab('show'); + popthis('Setup error.', 'The number of simulation periods is not an integer number.'); + return (0); + } + if (Number(simperiods) < 1) { + $('.nav-tabs a[href="#perforsetuptable"]').tab('show'); + popthis('Setup error.', 'The number of simulation periods can not be lower than 1.'); + return (0); + } + } + + // steady-state info check + if (ssstatus == 99) { + sstext = $('#perforSSblock').val(); + if (sstext.length == 0) { + $('.nav-tabs a[href="#perforsetuptable"]').tab('show'); + popthis('Steady state error.', 'Please provide a way to compute the steady-state.'); + return (0); + } + if ($('#issteadystateblock').is(":checked") == true) { + var sstype = 1; + } else { + var sstype = 2; + } + ssdescription.push({ + 'sstext': sstext, + 'sstype': parseInt(sstype, 10) + }); + } + + + + // Shocks tab checks + $('.nav-tabs a[href="#perforseqexp"]').tab('show'); + + var rowCount = $('#perforseqexptable tr').length - 1; // careful this counts the th row as a row, thus the -1 + + if (rowCount > 0) { + // there are shocks in the table + globalvaluescount = 1; + var xcond = 0; + var iter = 0; + var countshocks = 0; + + while (xcond == 0) { + // we iterate over global numshocks that kept track of shock indexes in any order they were entered + if (numshocks[iter] == 1) { + // if numshocks identifies a valid row in the table, we start further checks + countshocks = countshocks + 1; + shockvaluearray = []; + + // we fetch periods and values and anticipation dates + shockstart = $('#shockstart' + iter.toString()).val(); + shockstart = shockstart.trim(); + shockend = $('#shockend' + iter.toString()).val(); + shockend = shockend.trim(); + shockvalue = $('#shockvalues' + iter.toString()).val(); + shockvalue = shockvalue.trim(); + shockanticipdate = $('#shockanticipdate' + iter.toString()).val(); + shockanticipdate = shockanticipdate.trim(); + + ispermanent = 0; + isnonanticipated = 0; + isdelayed = 0; + previousdelay = 0 + previousnonanticip = 0; + + // we fetch the index of the shock given by the Dynare preprocessor + shockindex = $('#shockname' + iter.toString()).val(); + + // we verify if shock has been flagged as permanent or non anticipated + if ($("#shockpermanent" + iter.toString()).is(':checked')) { + permanentflag[shockindex] = permanentflag[shockindex] + 1; + permanentshockexist = 1; + ispermanent = 1; + if (nonanticipatedshockexist == 1) { + previousnonanticip = 1; + } + if (delayexist == 1) { + previousdelay = 1; + } + } + + if ($("#shockanticip" + iter.toString()).is(':checked')) { + nonanticipatedshockexist = 1; + isnonanticipated = 1; + } + + // we validate the anticipation date + if (shockanticipdate == null || shockanticipdate == "") { + shockanticipdate = 0; + } else { + if (!(Number.isInteger(Number(shockanticipdate)))) { + popthis('Shocks error.', 'The shock expectation date on row ' + countshocks + ' is not an integer number.'); + return (0); + } + if (Number(shockanticipdate) < 1) { + popthis('Shocks error.', 'The shock expectation date on row ' + countshocks + ' can not be lower than 1.'); + return (0); + } + delayexist = 1; + isdelayed = 1; + } + + if (permanentflag[shockindex] > 1) { + popthis('Shocks error.', 'You requested that shock ' + dynaremodel.exogenous[shockindex]["longName"] + ' is permanent in two or more instances. This is not supported, please specify only one permanent status per shock.'); + } + + + if (((ispermanent == 0) && (isnonanticipated == 0)) && (isdelayed == 0)) { + // the shock is not permanent or non anticipated or know with delay, user is supposed to enter periods + transitoryflag[shockindex] = 1; + // we validate the starting period + if (shockstart == null || shockstart == "") { + popthis('Shocks error.', 'You did not specify any starting period for shock on row ' + countshocks + '.'); + return (0); + } else { + if (!(Number.isInteger(Number(shockstart)))) { + popthis('Shocks error.', 'The shock starting period on row ' + countshocks + ' is not an integer number.'); + return (0); + } + if (Number(shockstart) < 1) { + popthis('Shocks error.', 'The shock starting period on row ' + countshocks + ' can not be lower than 1.'); + return (0); + } + shockstart = parseInt(shockstart, 10); + } + + // we validate the shock value + if (shockvalue == null || shockvalue == "") { + popthis('Shocks error.', 'You did not specify any value for shock on row ' + countshocks + '.'); + return (0); + } else { + if (!(IsNumeric(shockvalue))) { + // the user can enter several values separated by semicolon, we validate that + if (shockvalue.indexOf(';') > -1) { + columnsplit = shockvalue.split(';'); + columnsplitlength = columnsplit.length; + if ((columnsplit[columnsplitlength - 1] == null) || (columnsplit[columnsplitlength - 1] == "")) { + // we let the user end such an entry with a semicolon, but then reduce the length + columnsplitlength--; + } + if (columnsplitlength > 1) { + // if we are sure there should be at least 2 periods, we check the end period + if (shockend == null || shockend == "") { + popthis('Shocks error.', 'You did not specify any ending period for shock on row ' + countshocks + '.'); + return (0); + } else { + if (!(Number.isInteger(Number(shockend)))) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' is not an integer number.'); + return (0); + } + if (Number(shockend) > Number(simperiods)) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' can not be larger than the number of simulation periods.'); + return (0); + } + if (Number(shockend) < Number(shockstart)) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' cannot be before the shock starting period.'); + return (0); + } + shockend = parseInt(shockend, 10); + } + + // we verify if the number of periods and values match + if (!(columnsplitlength == (shockend - shockstart + 1))) { + popthis('Shocks error.', 'The number of periods and the number of shock values does not match on row ' + countshocks + '.'); + return (0); + } + + // we define a values array + for (i = 0; i < columnsplitlength; i++) { + if (!(IsNumeric(columnsplit[i]))) { + popthis('Shocks error.', 'At least one shock vector value on row ' + countshocks + ' is not a number.'); + return (0); + } + shockvaluearray.push(Number(columnsplit[i])); + } + } else { + // this is a single shock with just a start period + if (!(IsNumeric(columnsplit[0]))) { + popthis('Shocks error.', 'The shock value on row ' + countshocks + ' is not a number.'); + return (0); + } + shockvaluearray.push(Number(columnsplit[0])); + shockend = parseInt(shockstart, 10); + } + } else { + popthis('Shocks error.', 'The shock value on row ' + countshocks + ' is not a number.'); + return (0); + } + } else { + // the user did provide a single numeric value for the shock value + // the user can provide a single value and a start and end period, in that case the value is the same for this whole range, or just a start period + if (shockend == null || shockend == "") { + // this is a single shock with just a start period + if (!(IsNumeric(shockvalue))) { + popthis('Shocks error.', 'The shock value on row ' + countshocks + ' is not a number.'); + return (0); + } + shockend = parseInt(shockstart, 10); + shockvaluearray.push(Number(shockvalue)); + } else { + // this is a single value but with a range, we repeat the value over the range + if (!(Number.isInteger(Number(shockend)))) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' is not an integer number.'); + return (0); + } + if (Number(shockend) > Number(simperiods)) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' can not be larger than the number of simulation periods.'); + return (0); + } + shockend = parseInt(shockend, 10); + + // we define a values array + for (i = Number(shockstart); i < (Number(shockend) + 1); i++) { + shockvaluearray.push(Number(shockvalue)); + } + } + } + } + transitoryshockexist = 1; + // collecting the description of the shocks in an object + shocksdescription.push({ + 'shockindex': parseInt(shockindex, 10), + 'shockname': dynaremodel.exogenous[shockindex]["longName"], + 'shockstartperiod': shockstart, + 'shockendperiod': shockend, + 'shockvalue': shockvaluearray, + 'shocknonanticipated': isnonanticipated, + 'shockpermanent': ispermanent, + 'shockdelayed': isdelayed + }); + } + + // we want to rule out permanent shocks anticipated at date 1 or delayed permanent shocks with anticipation date 1, because basically it's the same thing as a permanent shock at date 1 + if ((ispermanent == 1) && ((isnonanticipated == 1) || (isdelayed == 1))) { + if (shockstart == null || shockstart == "") { + shockstart = 1; + } else { + if (!(Number.isInteger(Number(shockstart)))) { + popthis('Shocks error.', 'The shock starting period on row ' + countshocks + ' is not an integer number.'); + return (0); + } + if (Number(shockstart) < 1) { + popthis('Shocks error.', 'The shock starting period on row ' + countshocks + ' can not be lower than 1.'); + return (0); + } + shockstart = parseInt(shockstart, 10); + } + + // we validate the anticipation date + if (shockanticipdate == null || shockanticipdate == "") { + shockanticipdate = 0; + } else { + if (Number(shockanticipdate) > Number(shockstart)) { + popthis('Shocks error.', 'The shock expectation date on row ' + countshocks + ' can not be after the start date.'); + return (0); + } + // if ((nonanticipatedshockexist==1)&&(delayexist==1)){popthis('Shocks error.','Please either choose a non anticipated shock or a delayed anticipation shock with anticipation date for shock on row '+countshocks+', but not both.');return(0);} + } + + if ((isnonanticipated == 1) && (shockstart == 1)) { + isnonanticipated = 0; + if (previousnonanticip == 0) { + nonanticipatedshockexist = 0; + } + } + if ((isdelayed == 1) && (shockanticipdate == 1)) { + isdelayed = 0; + if (previousdelay == 0) { + delayexist = 0; + } + } + } + if (((ispermanent == 1) && (isnonanticipated == 0)) && (isdelayed == 0)) { + // the shock is permanent and anticipated, we allow only one value and ignore the ending period + + // we validate the starting period + if (shockstart == null || shockstart == "") { + shockstart = 1; + } else { + if (!(Number.isInteger(Number(shockstart)))) { + popthis('Shocks error.', 'The shock starting period on row ' + countshocks + ' is not an integer number.'); + return (0); + } + if (Number(shockstart) < 1) { + popthis('Shocks error.', 'The shock starting period on row ' + countshocks + ' can not be lower than 1.'); + return (0); + } + shockstart = parseInt(shockstart, 10); + } + + // we validate the shock value + if (shockvalue == null || shockvalue == "") { + popthis('Shocks error.', 'You did not specify any value for shock on row ' + countshocks + '.'); + return (0); + } else { + if (!(IsNumeric(shockvalue))) { + popthis('Shocks error.', 'The shock value on row ' + countshocks + ' is not numeric. A permanent shock can only have a single numeric value, no comma or semi-colon is authorized.'); + return (0); + } else { + // we collect the value + shockvaluearray.push(Number(shockvalue)); + } + } + + permanentshocksdescription.push({ + 'shockindex': parseInt(shockindex, 10), + 'shockname': dynaremodel.exogenous[shockindex]["longName"], + 'shockstartperiod': shockstart, + 'shockendperiod': shockend, + 'shockvalue': shockvaluearray, + 'shocknonanticipated': isnonanticipated, + 'shockpermanent': ispermanent, + 'shockdelayed': isdelayed + }); + } + + if ((isnonanticipated == 1) || (isdelayed == 1)) { + // the shock is either non anticipated or delayed + + // we validate the starting period + if (shockstart == null || shockstart == "") { + popthis('Shocks error.', 'You did not specify any starting period for shock on row ' + countshocks + '.'); + return (0); + } else { + if (!(Number.isInteger(Number(shockstart)))) { + popthis('Shocks error.', 'The shock starting period on row ' + countshocks + ' is not an integer number.'); + return (0); + } + if (Number(shockstart) < 1) { + popthis('Shocks error.', 'The shock starting period on row ' + countshocks + ' can not be lower than 1.'); + return (0); + } + shockstart = parseInt(shockstart, 10); + } + + // we validate the anticipation date + if (shockanticipdate == null || shockanticipdate == "") { + shockanticipdate = 0; + } else { + if (Number(shockanticipdate) > Number(shockstart)) { + popthis('Shocks error.', 'The shock expectation date on row ' + countshocks + ' can not be after the start date.'); + return (0); + } + } + + // we validate the shock value + if (shockvalue == null || shockvalue == "") { + popthis('Shocks error.', 'You did not specify any value for shock on row ' + countshocks + '.'); + return (0); + } else { + if (!(IsNumeric(shockvalue))) { + // the user can enter several values separated by semicolon, we validate that + if (shockvalue.indexOf(';') > -1) { + columnsplit = shockvalue.split(';'); + columnsplitlength = columnsplit.length; + if ((columnsplit[columnsplitlength - 1] == null) || (columnsplit[columnsplitlength - 1] == "")) { + // we let the user end such an entry with a semicolon, but then reduce the length + columnsplitlength--; + } + if (columnsplitlength > 1) { + // if we are sure there should be at least 2 periods, we check the end period + if (shockend == null || shockend == "") { + popthis('Shocks error.', 'You did not specify any ending period for shock on row ' + countshocks + '.'); + return (0); + } else { + if (!(Number.isInteger(Number(shockend)))) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' is not an integer number.'); + return (0); + } + if (Number(shockend) > Number(simperiods)) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' can not be larger than the number of simulation periods.'); + return (0); + } + if (Number(shockend) < Number(shockstart)) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' can before the shock starting period.'); + return (0); + } + shockend = parseInt(shockend, 10); + } + + // we verify if the number of periods and values match + if (!(columnsplitlength == (shockend - shockstart + 1))) { + popthis('Shocks error.', 'The number of periods and the number of shock values does not match on row ' + countshocks + '.'); + return (0); + } + + // we define a values array + for (i = 0; i < columnsplitlength; i++) { + if (!(IsNumeric(columnsplit[i]))) { + popthis('Shocks error.', 'At least one shock vector value on row ' + countshocks + ' is not a number.'); + return (0); + } + shockvaluearray.push(Number(columnsplit[i])); + } + } else { + // this is a single shock with just a start period + if (!(IsNumeric(columnsplit[0]))) { + popthis('Shocks error.', 'The shock value on row ' + countshocks + ' is not a number.'); + return (0); + } + shockvaluearray.push(Number(columnsplit[0])); + shockend = parseInt(shockstart, 10); + } + } else { + popthis('Shocks error.', 'The shock value on row ' + countshocks + ' is not a number.'); + return (0); + } + } else { + // the user did provide a single numeric value for the shock value + // the user can provide a single value and a start and end period, in that case the value is the same for this whole range, or just a start period + if (shockend == null || shockend == "") { + // this is a single shock with just a start period + if (!(IsNumeric(shockvalue))) { + popthis('Shocks error.', 'The shock value on row ' + countshocks + ' is not a number.'); + return (0); + } + shockend = parseInt(shockstart, 10); + shockvaluearray.push(Number(shockvalue)); + } else { + // this is a single value but with a range, we repeat the value over the range + if (!(Number.isInteger(Number(shockend)))) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' is not an integer number.'); + return (0); + } + if (Number(shockend) > Number(simperiods)) { + popthis('Shocks error.', 'The shock ending period on row ' + countshocks + ' can not be larger than the number of simulation periods.'); + return (0); + } + shockend = parseInt(shockend, 10); + + // we define a values array + for (i = Number(shockstart); i < (Number(shockend) + 1); i++) { + shockvaluearray.push(Number(shockvalue)); + } + } + } + } + + // defining special anticipation tracking + if (isdelayed == 1) { + nonanticipmatrix[trackrow] = new Array(9); + nonanticipmatrix[trackrow][0] = parseInt(shockanticipdate, 10); + nonanticipmatrix[trackrow][1] = parseInt(shockindex, 10); + if (ispermanent == 1) { + nonanticipmatrix[trackrow][2] = 1; + } else { + nonanticipmatrix[trackrow][2] = 0; + } + nonanticipmatrix[trackrow][3] = 1; + nonanticipmatrix[trackrow][4] = shockstart; + nonanticipmatrix[trackrow][5] = shockend; + nonanticipmatrix[trackrow][6] = shockvaluearray; + nonanticipmatrix[trackrow][8] = ""; + trackrow++; + } else { + cl("shockstart:" + shockstart); + cl("shockend:" + shockend); + icurrentloop = 0; + for (ixloop = shockstart; ixloop <= shockend; ixloop++) { + cl("ixloop:" + ixloop) + nonanticipmatrix[trackrow] = new Array(9); + nonanticipmatrix[trackrow][0] = ixloop; + nonanticipmatrix[trackrow][1] = parseInt(shockindex, 10); + if (ispermanent == 1) { + nonanticipmatrix[trackrow][2] = 1; + } else { + nonanticipmatrix[trackrow][2] = 0; + } + nonanticipmatrix[trackrow][3] = 0; + nonanticipmatrix[trackrow][6] = shockvaluearray[icurrentloop]; + nonanticipmatrix[trackrow][8] = ""; + icurrentloop++; + trackrow++; + } + } + + } + + + //we count the number of this specific shock + shocksflag[shockindex] = shocksflag[shockindex] + 1; + } + if (countshocks == rowCount) { + xcond = 1; + } + iter = iter + 1; + } + + + } + + + + if (globalvaluescount == 0) { + popthis('Simulation input error.', 'You have submitted no input to perform the simulation. Please input value(s) and retry.'); + return (0); + } else { + { //we post to the server + + nonanticipmatrix.sort(sortbyfirst); + nonanticipmatrix[trackrow] = new Array(9); + nonanticipmatrix[trackrow][0] = -1; + + if ((delayexist == 1) && (nonanticipatedshockexist == 1)) { + popthis('Warning.', 'You have specified that a shock is non-expected while providing an expectation date. Only the effect of the expectation date will be taken into account.'); + } + + var perforval = { + 'modelhash': $('#codehash').val(), + 'simperiods': parseInt(simperiods, 10), + 'ssstatus': parseInt(ssstatus, 10), + 'endonum': parseInt(endonum, 10), + 'exonum': parseInt(exonum, 10), + 'ssdescription': ssdescription, + 'shocksdescription': shocksdescription, + 'permanentshocksdescription': permanentshocksdescription, + 'transitoryshockexist': transitoryshockexist, + 'permanentshockexist': permanentshockexist, + 'nonanticipatedshockexist': nonanticipatedshockexist, + 'delayexist': delayexist, + 'nonanticipmatrix': nonanticipmatrix, + 'accesstype': 'runperfect', + 'jsontest': ["12"] + }; + + var perforvaldata = JSON.stringify(perforval); + $("#outputtable").empty(); + $("#plotbtn").empty(); + $("#plotbox").empty(); + $('#perforModal').modal('hide'); + var div = document.createElement('div'); + div.className = 'loader'; + div.innerHTML = ''; + document.getElementById('inner').appendChild(div); + $('.nav-tabs a[href="#output"]').tab('show'); + + // ajaxing content + + $.ajax({ + url: $(editorform).attr('action'), + headers: {'x-csrf-token': $('#_csrf').val()}, + type: "PUT", + contentType: "application/json", + dataType: 'json', + data: perforvaldata, + success: function(resp) { + + // var currentout = $("textarea#preprocessorout").val(); + // currentout = currentout + resp.data.message; + // $("textarea#preprocessorout").val(currentout); + + // else if (resp.data.status == 2) { //there were matlab errors + // $('.nav-tabs a[href="#console"]').tab('show'); + // $("#inner").empty(); + // document.getElementById("inner").innerHTML = '<p style="color:red;">Matlab errors found. See console.</p>'; + // } else if (resp.data.status == 3) { + // currentout = currentout + resp.data.message; + // $("textarea#preprocessorout").val(currentout + '\n \n The preprocessor could nor process your input. Please check the extra steady-state information you provided.'); + // $('.nav-tabs a[href="#console"]').tab('show'); + // $("#inner").empty(); + // document.getElementById("inner").innerHTML = '<p style="color:red;">Preprocessor errors found. See console.</p>'; + // } + + + if (resp.status == 200) { + console.log("200") + return popthis('Error', resp.message); + } else if (resp.status == 100) { + console.log("100") + showconsolealert(resp.message, 1); + console.log('console error'); + return false; + } + + console.log('All done here !') + + + + }, + error: function() { + console.log('there was a problem checking the fields'); + } + }); + return false; + } + } + +}); + + + +$(function () { + socket.on('perfectsimfinish', function(msg){ + // $('#messages').append($('<li>').text(msg)); + console.log(msg); + + + matlabdata = msg; + var endovarname; + + // creating output content + var sstbl1 = ` + <section> + <h2>Steady state results</h2> + <table class="table table-striped table-hover"> + <thead> + <tr> + <th>#</th> + <th>Endogenous variable</th> + <th>Initial Steady state</th> + <th>Final Steady state</th> + </tr> + </thead> + <tbody> + `; + + var plotdropdown = ` + <section> + <h2>Plots</h2> + <div class="btn-group" role="group" aria-label="..."> + <div class="btn-group" role="group"> + <button id="plotbtn" class="btn btn-primary btn-lg dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + Select graph <span class="caret"></span><span class="sr-only">Toggle Dropdown</span> + </button> + <ul class="dropdown-menu" aria-labelledby="plotbtn"> + <li class="dropdown-header">Endogenous variables:</li> + `; + y = 0; + for (x in matlabdata.endo_names) { + endovarname = matlabdata.endo_names[x].trim(); + plotdropdown += '<li onclick="plotmethis("' + endovarname + '")"><a href="#stophere">' + endovarname + '</a></li>'; + y = y + 1; + sstbl1 += '<tr><th scope="row">' + y + '</th>'; + sstbl1 += "<td>" + endovarname + "</td>"; + sstbl1 += "<td>" + matlabdata.steady_state1[x] + "</td>"; + sstbl1 += "<td>" + matlabdata.steady_state2[x] + "</td>"; + } + plotdropdown +='</ul></div>'; + plotdropdown +=` + <div class="btn-group" role="group"> + <button id="exportbtn" class="btn btn-primary btn-lg dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + Export data <span class="caret"></span><span class="sr-only">Toggle Dropdown</span> + </button> + <ul class="dropdown-menu" aria-labelledby="exportbtn"> + <li class="dropdown-header">Select file type:</li> + <li onclick="exportfile("json")"><a href="#stophere">Export to JSON</a></li> + <li onclick="exportfile("csv")"><a href="#stophere">Export to CSV</a></li> + </ul> + </div>`; + + plotdropdown += ` + </div> + </section> + `; + sstbl1 += "</tbody></table></section>"; + $("#inner").empty(); + document.getElementById("outputtable").innerHTML = sstbl1; + document.getElementById("plotbtn").innerHTML = plotdropdown; + + + plotmethis(matlabdata.endo_names[0].trim()); + + + + + + + }); + }); + + + + +// $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ output + +// graph plotter +function plotmethis(plotvar) { + + var trace1 = { + x: matlabdata.endo_simul.plotx, + y: matlabdata.endo_simul[plotvar] + }; + var data = [trace1]; + + var layout = { + title: plotvar, + xaxis: { + title: 'Periods' + }, + yaxis: { + title: plotvar + } + }; + + Plotly.newPlot('plotbox', data, layout); +} + +// files exporter +function exportfile(exporttype) { + + var filename = $('#codename').val(); + + if (exporttype == 'json') { + var exportjson = { + 'simulation': [], + 'steadystate1': matlabdata.steady_state1, + 'steadystate2': matlabdata.steady_state2 + }; + for (var key in matlabdata.endo_simul) { + if (key != "plotx") { + exportjson.simulation.push({ + [key]: matlabdata.endo_simul[key] + }); + } + } + var exportjsontext = JSON.stringify(exportjson); + download(filename + ".JSON", exportjsontext); + } + + if (exporttype == 'csv') { + var exportcsv = matlabdata.endo_names + "\r\n"; + var csvarray = []; + for (var mykey in matlabdata.endo_names) { + csvarray.push(matlabdata.endo_simul[matlabdata.endo_names[mykey]]); + cl(mykey); + } + var transpose = csvarray[0].map((col, i) => csvarray.map(row => row[i])); + for (itr = 0; itr < transpose.length; itr++) { + exportcsv += transpose[itr] + "\r\n"; + } + download(filename + ".csv", exportcsv); + } +} diff --git a/public/static/js/stochastic.js b/public/static/js/stochastic.js index cb653eafe83685061a3c34a133fda4156e8689f1..aa8d9ea03e15d75d298d2d85077b095758d66b9c 100644 --- a/public/static/js/stochastic.js +++ b/public/static/js/stochastic.js @@ -28,7 +28,7 @@ for (i = 0; i < 1000; i++) { //------------------------------------------------------------@@@button set perfect -$('#setstochastic').click(function() { +$('#setstochastic').click(function () { // let basedir = path.resolve(__dirname, './assets/modfiles/'); @@ -50,10 +50,12 @@ $('#setstochastic').click(function() { $.ajax({ url: $(editorform).attr('action'), - headers: {'x-csrf-token': $('#_csrf').val()}, + headers: { + 'x-csrf-token': $('#_csrf').val() + }, type: "POST", data: modelcode, - success: function(resp) { + success: function (resp) { if (resp.status == 200) { console.log("200") @@ -65,52 +67,53 @@ $('#setstochastic').click(function() { return false; } + showconsolealert(resp.message, 1); + var currentdate = new Date(); + $('#classlist-form-messages').text('Last saved at: ' + currentdate); - showconsolealert(resp.message, 1); - - //the model has exo shocks: we make a table - // if a steady state has not been provided if ask extra info on that - dynaremodel = resp.modeljson; + //the model has exo shocks: we make a table + // if a steady state has not been provided if ask extra info on that + dynaremodel = resp.modeljson; - // steady-state compute table - document.getElementById("stosimssinittable").innerHTML = ""; - if (resp.status == 201) { - var extrassinfo = ""; - var extrasshelp = ""; - if (resp.extrassinfo !== null) { - extrassinfo = resp.extrassinfo; - extrasshelp = " (the last known steady-state info have been loaded below)" - } - var extrasstype = ""; - if (resp.extrasstype == 1) { - extrasstype = 'checked'; - } + // steady-state compute table + document.getElementById("stosimssinittable").innerHTML = ""; + if (resp.status == 201) { + var extrassinfo = ""; + var extrasshelp = ""; + if (resp.extrassinfo !== null) { + extrassinfo = resp.extrassinfo; + extrasshelp = " (the last known steady-state info have been loaded below)" + } + var extrasstype = ""; + if (resp.extrasstype == 1) { + extrasstype = 'checked'; + } - sscomputeeendo = ` + sscomputeeendo = ` <h4>Steady state</h4> <p style="color:#3399CC">You did not provide any way to compute the steady-state. Please specify a way to compute the steady-state` + extrasshelp + `.</p> <div class="form-group no-margin"> <textarea class="form-control" id="stoSSblock" name="stoSSblock" placeholder="Steady-state equations;" rows="7">` + extrassinfo + `</textarea> </div> <div class="form-group no-margin"><label><input type="checkbox" name="stoissteadystateblock" id="stoissteadystateblock"` + extrasstype + `/> Check if the above will compute the exact steady-state (will be interpreted as a <span style="font-style: italic;">steady_state_model</span> block). Leave unchecked if the above should be used as a starting point to compute the steady-state (will be interpreted as an <span style="font-style: italic;">initval</span> block).</label></div> <input id="stomodelsteadystatestatus" name="stomodelsteadystatestatus" value="99" type="hidden"> `; - } else if (resp.status == 2) { - sscomputeeendo = ` + } else if (resp.status == 2) { + sscomputeeendo = ` <input id="stomodelsteadystatestatus" name="stomodelsteadystatestatus" value="55" type="hidden"> `; - } else { - sscomputeeendo = ` + } else { + sscomputeeendo = ` <input id="stomodelsteadystatestatus" name="stomodelsteadystatestatus" value="0" type="hidden"> `; - } - document.getElementById("stosimssinittable").innerHTML = sscomputeeendo; - document.getElementById("stomodel_endonum").value = (dynaremodel.endogenous).length; - document.getElementById("stomodel_exonum").value = (dynaremodel.exogenous).length; - $('#stosimModal').modal('show'); + } + document.getElementById("stosimssinittable").innerHTML = sscomputeeendo; + document.getElementById("stomodel_endonum").value = (dynaremodel.endogenous).length; + document.getElementById("stomodel_exonum").value = (dynaremodel.exogenous).length; + $('#stosimModal').modal('show'); }, - error: function() { + error: function () { console.log('there was a problem checking the fields'); } }); @@ -447,23 +450,7 @@ $('#runstochastic').click(async function () { return false; - // // calling the 'node side' - // try { - // var resp = await runstochasticnode(stosimval); - // } catch (error) { - // console.log(error) - // if (error.status == 200) { - // console.log("200") - // return popthis('Error', error.message); - // } else if (error.status == 100) { - // console.log("100") - // showconsolealert(error.message, 1); - // console.log('console error'); - // return false; - // } - // } - - // return false; + } } diff --git a/routes/index.js b/routes/index.js index e067387de8f66c70900d41675ce93071fcd61351..f0372378101182629b3e89cd69e10897db99c4db 100644 --- a/routes/index.js +++ b/routes/index.js @@ -7,9 +7,10 @@ var cookieParser = require('cookie-parser'); const getmodelfromdb = require('../appModules').getmodelfromdb; const savetodb = require('../appModules').savetodb; const newmodelindb = require('../appModules').newmodelindb; -const setpreprocess = require('../middleware/runpreprocess').setpreprocess; -const setstochasticnode = require('../middleware/runstochastic').setstochasticnode; -const runstochasticnode = require('../middleware/runstochastic').runstochasticnode; +const setpreprocess = require('../middleware/runprocesses').setpreprocess; +const setpreprocessmore = require('../middleware/runprocesses').setpreprocessmore; +const runstochasticnode = require('../middleware/runprocesses').runstochasticnode; +const runperfectnode = require('../middleware/runprocesses').runperfectnode; // const ipc = require('node-ipc'); const csrfProtection = csrf({ @@ -132,7 +133,7 @@ router.post('/', function (req, res) { case 'setstochastic': - setstochasticnode(req.body) + setpreprocessmore(req.body) .then(function (data) { console.log(data); res.json(data); @@ -145,6 +146,22 @@ router.post('/', function (req, res) { break; + + case 'setperfect': + + console.log('Got setperfect'); + + setpreprocessmore(req.body) + .then(function (data) { + console.log(data); + res.json(data); + }) + .catch(function (e) { + res.json(data); + }); + + break; + default: res.json({ 'status': 999, @@ -176,6 +193,22 @@ router.put('/', function (req, res) { break; + case 'runperfect': + + console.log('Got runperfect'); + + runperfectnode(req.body) + .then(function (data) { + console.log(data); + res.json(data); + }) + .catch(function (e) { + res.json(data); + }); + + break; + + default: res.json({ 'status': 999, diff --git a/views/index.handlebars b/views/index.handlebars index 9bb444c5930132f1ba57cd62ec3e3fbba374f92b..025495a7786ed2077dc4e1bd2f0792a43a8b94a8 100644 --- a/views/index.handlebars +++ b/views/index.handlebars @@ -401,7 +401,7 @@ <script src="./static/js/dynareinterface.js"></script> <script src="./static/js/editor.js"></script> - <!-- <script src="./static/js/perfectforesight.js"></script> --> + <script src="./static/js/perfectforesight.js"></script> <script src="./static/js/stochastic.js"></script> <script>