From 299b7f8f58781e0ceb3989e6f0941434fbf9b0ea Mon Sep 17 00:00:00 2001 From: Justin Merz Date: Fri, 13 Nov 2015 12:28:43 -0800 Subject: [PATCH] first working example of complete pri/dss build --- export/nodejs/dss/cost.js | 45 +++++----------- export/nodejs/dss/elArCap.js | 18 ++----- export/nodejs/dss/evaporation.js | 16 ++++++ export/nodejs/dss/flow.js | 17 +++++++ export/nodejs/dss/index.js | 6 ++- export/nodejs/dss/inflow.js | 17 +++++++ export/nodejs/dss/path.js | 30 ++++++++--- export/nodejs/dss/timeBound.js | 9 ++-- export/nodejs/pri/format/link.js | 79 ++++++++++++++++++++++------- export/nodejs/pri/format/utils.js | 2 +- export/nodejs/prm/cmds/build.js | 71 +++++++++----------------- export/nodejs/prm/cmds/showBuild.js | 45 ++++++++-------- export/nodejs/prm/lib/runtime.js | 30 +++++++---- 13 files changed, 230 insertions(+), 155 deletions(-) create mode 100644 export/nodejs/dss/evaporation.js create mode 100644 export/nodejs/dss/flow.js create mode 100644 export/nodejs/dss/inflow.js diff --git a/export/nodejs/dss/cost.js b/export/nodejs/dss/cost.js index 84564c820..a241a896b 100644 --- a/export/nodejs/dss/cost.js +++ b/export/nodejs/dss/cost.js @@ -3,36 +3,17 @@ var fs = require('fs'); var path = require('./path'); -module.exports = function(properties) { - var costs = properties.costs; - var results = []; - - if( !costs ) { - return results; - } - - if( costs.type === 'Monthly Variable' ) { - for( var month in costs.costs ) { - var file = costs.costs[month]; - - if( !fs.existsSync(file) ) { - console.log('WARNING: '+file+' does not exist'); - } - - results.push({ - csvFilePath : file, - type : 'paired', - label : month, - date : month, - location : properties.prmname, - xunits : 'KAF', - xtype : 'DIVR', - yunits : 'Penalty', - ytype : '', - path : path.monthlyPq(properties.prmname, month, 'dss') - }); - } - } - - return results; +module.exports = function(prmname, month, file) { + return { + csvFilePath : file, + type : 'paired', + label : month, + date : month, + location : prmname, + xunits : 'KAF', + xtype : 'DIVR', + yunits : 'Penalty', + ytype : '', + path : path.monthlyPq(prmname, month, 'dss') + }; }; diff --git a/export/nodejs/dss/elArCap.js b/export/nodejs/dss/elArCap.js index 9889b7635..a58a12d04 100644 --- a/export/nodejs/dss/elArCap.js +++ b/export/nodejs/dss/elArCap.js @@ -3,26 +3,16 @@ var fs = require('fs'); var path = require('./path'); -module.exports = function(properties) { - var el_ar_cap = properties.el_ar_cap; - - if( !el_ar_cap ) { - return {}; - } - - if( !fs.existsSync(el_ar_cap) ) { - console.log('WARNING: '+el_ar_cap+' does not exist'); - } - +module.exports = function(prmname, file) { return { - csvFilePath : el_ar_cap, + csvFilePath : file, type : 'paired', label : 'EL', - location : properties.prmname, + location : prmname, xunits : 'FT', xtype : 'UNT', yunits : 'KA', ytype : '', - path : path.eac(properties.prmname, 'dss') + path : path.eac(prmname, 'dss') }; }; diff --git a/export/nodejs/dss/evaporation.js b/export/nodejs/dss/evaporation.js new file mode 100644 index 000000000..df9387aa0 --- /dev/null +++ b/export/nodejs/dss/evaporation.js @@ -0,0 +1,16 @@ +'use strict'; + +var fs = require('fs'); +var path = require('./path'); + +module.exports = function(prmname, file) { + return { + csvFilePath : file, + type : 'timeseries', + parameter : 'EVAP_RATE(FT)', + location : prmname, + units : 'KAF', + xtype : 'PER-AVER', + path : path.evapo(prmname, 'dss') + }; +}; diff --git a/export/nodejs/dss/flow.js b/export/nodejs/dss/flow.js new file mode 100644 index 000000000..2c36ea4b9 --- /dev/null +++ b/export/nodejs/dss/flow.js @@ -0,0 +1,17 @@ +'use strict'; + +var fs = require('fs'); +var path = require('./path'); + +module.exports = function(prmname, file) { + + return { + csvFilePath : file, + type : 'timeseries', + parameter : 'FLOW_LOSS(KAF)', + location : prmname, + units : 'KAF', + xtype : 'PER-AVER', + path : path.flow(prmname, 'dss') + }; +}; diff --git a/export/nodejs/dss/index.js b/export/nodejs/dss/index.js index 625e60588..81605b711 100644 --- a/export/nodejs/dss/index.js +++ b/export/nodejs/dss/index.js @@ -1,5 +1,9 @@ module.exports = { path : require('./path'), eac : require('./elArCap'), - cost : require('./cost') + cost : require('./cost'), + flow : require('./flow'), + inflow : require('./inflow'), + evapo: require('./evaporation'), + bound : require('./timeBound') }; diff --git a/export/nodejs/dss/inflow.js b/export/nodejs/dss/inflow.js new file mode 100644 index 000000000..7897d405c --- /dev/null +++ b/export/nodejs/dss/inflow.js @@ -0,0 +1,17 @@ +'use strict'; + +var fs = require('fs'); +var path = require('./path'); + +module.exports = function(prmname, name, file) { + + return { + csvFilePath : file, + type : 'timeseries', + parameter : 'FLOW_LOC(KAF)', + location : prmname, + units : 'KAF', + xtype : 'PER-AVER', + path : path.in(prmname, name, 'dss') + }; +}; diff --git a/export/nodejs/dss/path.js b/export/nodejs/dss/path.js index 874ec2fff..a22989d8e 100644 --- a/export/nodejs/dss/path.js +++ b/export/nodejs/dss/path.js @@ -1,15 +1,31 @@ 'use strict'; var utils = require('../pri/format/utils'); -function writeTimeBound(type, prmname) { +/** + outputType == 'dss' || 'pri' +**/ + +// Bound types: +// STOR: Storage +// FLOW: flow +function writeTimeBound(type, prmname, boundType, outputType) { return utils.parts(type, { B : prmname, // TODO: is this correct? - C : 'STOR_'+(type === 'UB' ? 'UBT' : 'LBT')+'(KAF)' - }); + C : boundType+'_'+(type === 'QU' ? 'UBT' : 'LBT')+'(KAF)', + E : '1MON' + }, outputType); //A=HEXT2014 B=SR-CMN_SR-CMN C=STOR_UBT(KAF) E=1MON F=CAMANCHE R FLOOD CAP } +function writeFlow(prmname) { + return utils.parts('', { + B : prmname, + C : 'FLOW_LOSS(KAF)', + E : '1MON' + }); +} + function writeMonthlyPq(prmname, month, outputType) { return utils.parts('PQ',{ MO : month, @@ -23,7 +39,7 @@ function writeIn(prmname, name, outputType) { return utils.parts('IN',{ B : prmname, C : 'FLOW_LOC(KAF)', - // E : '1MON' ... assumed + E : '1MON', F: name }, outputType); } @@ -31,14 +47,15 @@ function writeIn(prmname, name, outputType) { function writeEvapo(prmname, outputType) { return utils.parts('EV',{ B : prmname, - C : 'EL-AR-CAP' + C : 'EVAP_RATE(FT)', + E : '1MON' }, outputType); } function writeEAC(prmname, outputType) { return utils.parts('EAC',{ B : prmname, - C : 'EVAP_RATE(FT)' + C : 'EL-AR-CAP' }, outputType); } @@ -54,6 +71,7 @@ function writeEmptyPq() { module.exports = { timeBound : writeTimeBound, monthlyPq : writeMonthlyPq, + flow : writeFlow, in : writeIn, evapo : writeEvapo, eac : writeEAC, diff --git a/export/nodejs/dss/timeBound.js b/export/nodejs/dss/timeBound.js index 6802080bc..db347adab 100644 --- a/export/nodejs/dss/timeBound.js +++ b/export/nodejs/dss/timeBound.js @@ -3,16 +3,15 @@ var fs = require('fs'); var path = require('./path'); -module.exports = function(prmname, file) { +module.exports = function(type, prmname, boundType, file) { return { csvFilePath : file, type : 'timeseries', parameter : '1MON', - xunits : 'FT', + xunits : 'KAF', + location : prmname, xtype : 'UNT', - yunits : 'KA', - ytype : '', - path : path.timeBound(prmname, 'dss') + path : path.timeBound(type, prmname, boundType, 'dss') }; }; diff --git a/export/nodejs/pri/format/link.js b/export/nodejs/pri/format/link.js index e4145b46c..a3e0dea29 100644 --- a/export/nodejs/pri/format/link.js +++ b/export/nodejs/pri/format/link.js @@ -2,6 +2,7 @@ var sprintf = require('sprintf-js').sprintf; var utils = require('./utils'); +var fs = require('fs'); var dss = require('../../dss'); // from page 58 of manual @@ -24,8 +25,7 @@ for( var i = 0; i < LINK_SPACING.length; i++ ) { module.exports = function(config, node, type) { var np = node.properties; - var link = writeLink(config, np, type || 'DIVR'); - return link; + writeLink(config, np, type || 'DIVR'); }; function writeLink(config, np, type) { @@ -41,8 +41,21 @@ function writeLink(config, np, type) { var inf = ''; var cost = '', lowerBound = '', upperBound = '', constantBound = ''; + var prmname = np.prmname; + if( np.type === 'Surface Storage' ) { + prmname = prmname+'_'+prmname; + } + // do we have bounds if( np.bounds ) { + + var boundType; + if( np.type === 'Surface Storage' ) { + boundType = 'STOR'; + } else { + boundType = 'FLOW'; + } + // add constant bounds for( var i = 0; i < np.bounds.length; i++ ) { var bound = np.bounds[i]; @@ -58,11 +71,21 @@ function writeLink(config, np, type) { } else if( bound.type === 'LBM' ) { b += writeMonthlyBound('LB', bound)+'\n'; } else if( bound.type === 'UBT' ) { - b += dss.path.timeBound('QU', np.prmname)+'\n'; + if( !fs.existsSync(bound.bound) ) { + console.log('File not found, ignoring: '+bound.bound); + continue; + } + // set pri path + b += dss.path.timeBound('QU', prmname, boundType)+'\n'; + // set dss writer json object + config.ts.data.push(dss.bound('QU', prmname, boundType, bound.bound)); + - } else if( bound.type === 'LBT' ) { - b += dss.path.timeBound('QL', np.prmname)+'\n'; + // set pri path + b += dss.path.timeBound('QL', prmname, boundType)+'\n'; + // set dss writer json object + config.ts.data.push(dss.bound('QL', prmname, boundType, bound.bound)); } } } @@ -71,7 +94,15 @@ function writeLink(config, np, type) { // Monthly Variable Types Require a PQ if( np.costs.type === 'Monthly Variable' ) { for( var month in np.costs.costs ){ - pq += dss.path.monthlyPq(month, np.prmname)+'\n'; + if( !fs.existsSync(np.costs.costs[month]) ) { + console.log('File not found, ignoring: '+np.costs.costs[month]); + continue; + } + + // set pri path + pq += dss.path.monthlyPq(month, prmname)+'\n'; + // set dss writer json object + config.pd.data.push(dss.cost(prmname, month, np.costs.costs[month])); } } else if( np.costs.cost >= 0 ) { @@ -79,28 +110,42 @@ function writeLink(config, np, type) { //IF COST IS ZERO, we need a PQ } else { - pq += dss.path.emptyPq()+'\n'; - } - - var dssEntries = dss.costs(np); - for( var i = 0; i < dssEntries.length; i++ ) { - config.pri.pd.data.push(dssEntries[i]); + pq += dss.path.empty()+'\n'; } } if( np.el_ar_cap ) { - eac = dss.path.eac(np.prmname)+'\n'; - config.pri.pd.data.push(dss.eac(np)); + if( !fs.existsSync(np.el_ar_cap) ) { + console.log('File not found, ignoring: '+np.el_ar_cap); + } else { + eac = dss.path.eac(prmname)+'\n'; + config.pd.data.push(dss.eac(np.prmname, np.el_ar_cap)); + } } + if( np.inflows ) { for( var name in np.inflows ) { - config.pri.inflowlist.push(writeIn(np.prmname, name)); + if( !fs.existsSync(np.inflows[name].inflow) ) { + console.log('File not found, ignoring: '+np.inflows[name].inflow); + continue; + } + + config.pri.inflowlist.push(writeIn(prmname, name)); + + // set dss writer json object + config.ts.data.push(dss.inflow(prmname, name, np.inflows[name].inflow)); } } if( np.evaporation ) { - ev = dss.path.evapo(np.prmname)+'\n'; + if( !fs.existsSync(np.evaporation) ) { + console.log('File not found, ignoring: '+np.evaporation); + } else { + ev = dss.path.evapo(prmname)+'\n'; + // set dss writer json object + config.ts.data.push(dss.evapo(prmname, np.evaporation)); + } } var link = ''; @@ -116,7 +161,7 @@ function writeLink(config, np, type) { } if( np.type === 'Surface Storage' ) { - link = sprintf(LINK_FORMAT, 'LINK', '', 'RSTO', np.prmname, np.prmname, amplitude, cost, lowerBound, upperBound, constantBound)+'\n'; + link = sprintf(LINK_FORMAT, 'LINK', '', 'RSTO', prmname, prmname, amplitude, cost, lowerBound, upperBound, constantBound)+'\n'; link += sprintf('%-8.8s %-80.80s', 'LD', np.description || '')+'\n'; link += b; link += ev; diff --git a/export/nodejs/pri/format/utils.js b/export/nodejs/pri/format/utils.js index e2e58daba..84fb52fa0 100644 --- a/export/nodejs/pri/format/utils.js +++ b/export/nodejs/pri/format/utils.js @@ -6,7 +6,7 @@ module.exports.months = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP',' module.exports.parts = function(type, p, outputType) { if( outputType === 'dss' ) { - return sprintf('/%s/%s/%s/%s/%s/%s', + return sprintf('/%s/%s/%s/%s/%s/%s/', (p.A) ? p.A : '', (p.B) ? p.B : '', (p.C) ? p.C : '', diff --git a/export/nodejs/prm/cmds/build.js b/export/nodejs/prm/cmds/build.js index ce8435b25..282fc4e4d 100644 --- a/export/nodejs/prm/cmds/build.js +++ b/export/nodejs/prm/cmds/build.js @@ -6,6 +6,7 @@ var path = require('path'); var crawler = require('../../crawler'); var runtime = require('../lib/runtime'); var costs = require('../../dss/cost'); +var prepare = require('../lib/prepare'); var options; var args; @@ -17,67 +18,41 @@ module.exports = function(argv) { }; function onCrawlComplete(results){ - var dssPenalties = { - path : path.join(options.output || getUserHome(), options.prefix+'PD.dss'), - data : [] - }; - - /* TODO - var config = prepare(results.nodes); + var config = prepare.init(); config.pd.path = path.join(options.output || getUserHome(), options.prefix+'PD.dss'); - runtime(options.runtime, config.pd, function(err, resp){ - runtime(options.runtime, config.ts, function(err, resp){ - fs.writeFileSync('foo.pri', create(config.pri)); + config.ts.path = path.join(options.output || getUserHome(), options.prefix+'TS.dss'); + var priPath = path.join(options.output || getUserHome(), options.prefix+'.pri'); + + for( var i = 0; i < results.nodes.length; i++ ) { + prepare.format(results.nodes[i], config); + } + + console.log('Writing PRI file: '+priPath); + fs.writeFileSync(priPath, prepare.pri(config)); + + console.log('Writing Penalty DSS file: '+config.pd.path); + writeDssFile(config.pd, function(err, resp){ + console.log('Writing TimeSeries DSS file: '+config.ts.path); + writeDssFile(config.ts, function(err, resp){ + console.log('Done.'); }); }); - */ - console.log('Writing Penalties DSS file: '+dssPenalties.path); - runtime(options.runtime, dssPenalties, function(err, resp){ +} + +function writeDssFile(dss, callback) { + runtime(args.runtime, dss, args.debugRuntime, function(err, resp){ if( err ) { console.log('ERROR: writing to dss file.'); console.log(err); - return; + //return; } - console.log('Done.'); - if( args.verbose ) { console.log(resp.stack); } - }); -} - -function addTimeSeries(dataArray, node) { - var costs = node.properties.costs; - - if( costs.type === 'Monthly Variable' ) { - for( var month in costs.costs ) { - var file = costs.costs[month]; - if( !fs.existsSync(file) ) { - console.log('WARNING: '+file+' does not exist'); - } - - dataArray.push({ - csvFilePath : file, - type : 'paired', - label : month, - date : month, - location : node.properties.prmname, - xunits : 'KAF', - xtype : 'DIVR', - yunits : 'Penalty', - ytype : '', - path : '//'+node.properties.prmname+'///'+month+'/1/' - }); - } - } -} -function addCost(dataArray, node) { - var results = costs(node); - results.forEach(function(result){ - dataArray.push(result); + callback(); }); } diff --git a/export/nodejs/prm/cmds/showBuild.js b/export/nodejs/prm/cmds/showBuild.js index fb5acf0cd..9b4f90aa8 100644 --- a/export/nodejs/prm/cmds/showBuild.js +++ b/export/nodejs/prm/cmds/showBuild.js @@ -2,10 +2,11 @@ var crawler = require('../../crawler'); var parse = require('csv-parse'); +var prepare = require('../lib/prepare'); var async = require('async'); var fs = require('fs'); -module.exports = function(type, argv) { +module.exports = function(argv) { if( argv._.length === 0 ) { console.log('You need to supply a prmname to show'); process.exit(-1); @@ -24,10 +25,12 @@ module.exports = function(type, argv) { process.exit(-1); } + var config = prepare.init(); crawler(data, {parseCsv : false}, function(results){ for( var i = 0; i < results.nodes.length; i++ ) { if( results.nodes[i].properties.prmname === prmname ) { - print(type, results.nodes[i], argv.showData); + prepare.format(results.nodes[i], config); + print(config, argv.showData); return; } } @@ -36,38 +39,36 @@ module.exports = function(type, argv) { }); }; -function print(type, node, showData) { - var results = []; - if( type === 'pd' ) { - results = require('../lib/build/cost')(node); - } else if( type === 'el' ) { - results.push(require('../lib/build/elArCap')(node)); - } else { - console.log('Unsupported type: '+type); - return; +function print(config, showData) { + console.log('*** Time Series ***'); + var csvFiles = []; + for( var i = 0; i < config.ts.data.length; i++ ) { + console.log(config.ts.data[i]); + csvFiles.push(config.ts.data[i].csvFilePath); + } + console.log('*** Penalty ***'); + for( var i = 0; i < config.pd.data.length; i++ ) { + console.log(config.pd.data[i]); + csvFiles.push(config.pd.data[i].csvFilePath); } if( !showData ) { - console.log(results); return; } async.eachSeries( - results, - function(result, next) { - if( !fs.existsSync(result.csvFilePath) ) { + csvFiles, + function(file, next) { + if( !fs.existsSync(file) ) { + console.log('Unabled to find: '+file); return next(); } - parse(fs.readFileSync(result.csvFilePath, 'utf-8'), {comment: '#', delimiter: ','}, function(err, data){ - result.csvData = data; + parse(fs.readFileSync(file, 'utf-8'), {comment: '#', delimiter: ','}, function(err, data){ + console.log(data); next(); }); }, - function() { - for( var i = 0; i < results.length; i++ ) { - console.log(results[i]); - } - } + function() {} ); } diff --git a/export/nodejs/prm/lib/runtime.js b/export/nodejs/prm/lib/runtime.js index c0a635373..31fc7ce9a 100644 --- a/export/nodejs/prm/lib/runtime.js +++ b/export/nodejs/prm/lib/runtime.js @@ -13,10 +13,14 @@ var exec = require('child_process').exec; // by the jar and parsed using the jackson lib. var PARAMS_TMP_FILE = '.dssWriterParams'; -module.exports = function(lib, params, callback) { +module.exports = function(lib, params, keep, callback) { + if( typeof keep === 'function' ) { + callback = keep; + } + // create tmp file in current working directory var paramFile = path.join(process.cwd(), PARAMS_TMP_FILE); - fs.writeFileSync(paramFile, JSON.stringify(params)); + fs.writeFileSync(paramFile, JSON.stringify(params, ' ', ' ')); // run the custom dssWriter jar using the packaged java (Win 32bit), HEC's java lib and HEC's system DLL's // (DLL's supplied with -Djava.library.path). The jar takes as it's first parameter the path to the tmp file. @@ -31,11 +35,13 @@ module.exports = function(lib, params, callback) { var cwd = path.join(lib, 'jre', 'bin'); // run - exec(cmd, {cwd: cwd}, + exec(cmd, {maxBuffer: 1024 * 500, cwd: cwd}, function (error, stdout, stderr) { // first thing after program runs, remove the tmp file - // TODO: perhaps a flag to keep this file around for possible debug? - fs.unlinkSync(paramFile); + if( keep !== true ) { + fs.unlinkSync(paramFile); + } + writeResponse(stdout, error, stderr, callback); } ); @@ -48,10 +54,16 @@ function writeResponse(stdout, error, stderr, callback) { // the HEC java lib pollutes stdout. the custom dssWriter throws some // JSON in there as well to communicate back to us. See if we can find // it. - var json = stdout.match(/\{.*\}/); - var stack = stdout.replace(json, ''); - json = JSON.parse(json); - json.stack = stack; + var json = { + message : 'If you see this, max buffer proly exceeded', + stack : '' + }; + if( stdout.match(/\{.*\}/) ){ + json = stdout.match(/\{.*\}/); + var stack = stdout.replace(json, ''); + json = JSON.parse(json); + json.stack = stack; + } callback(null, json); } catch(e) {