Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- "use strict"
- /**!
- * @licence
- *
- * Copyright Notice:
- *
- * The material in this file is protected by copyright.
- *
- * Copyright of this file is owned by C.W.A.M. van Overveld, Eindhoven, the Netherlands
- *
- * It is permitted to use, copy or modify this file under the following conditions:
- *
- * * Commercial use is forbidden without prior written permission by the copyright owner;
- * * This copyright message is to be left in the top of the file (also in case of minification);
- * * If this file is included in, or can be downloaded from a website, the website should contain
- * a link to www.keesvanoverveld.com and a message that states the copyright of this file;
- * * The author takes no responsabilities for any consequences that should follow from using
- * the contents of this file.
- *
- */
- var userGraph = function() {
- var graphContour = "graph"
- var autoScale = true;
- var exactClamp = false;
- // autoscale governs the vertical scaling of the graph.
- // it is always true, except if the user overrules the range from- and true values.
- // Normally, the values computed by autoscaling are made nice, that is: not too many decimals.
- // and a little room on both sides of the graph.
- // It can be convenient, however, to have the graph range adjusted exactly to the min and max values
- // attained. In that case, exactClamp should be true.
- var argVar = '';
- var coArgVar = '';
- var rangeVar = '';
- var argFrom = 0.0;
- var coArgFrom = 0.0;
- var argTo = 0.0;
- var coArgTo = 0.0;
- var rangeFrom = 0.0;
- var rangeTo = 0.0;
- var that = this;
- var rememberState = true;
- // this ensures that on a re-visit of the analysis tab, if the script has not been updated,
- // we update the graph with the recent cat.-I values.
- var msgHasBeenGiven = false
- // to limit the numeber of stack-overflow warnings
- var wrongGraph = {
- 'background': {
- 'fcol_a': 1,
- 'fcol_r': 153,
- 'fcol_g': 51,
- 'fcol_b': 204
- },
- 'locations': {
- 'x': 50,
- 'y': 50,
- 'tag': 'no graph',
- 'pointSize': 4,
- 'tcol_r': 255,
- 'tcol_g': 255,
- 'tcol_b': 255
- }
- }
- var lastFunctionReport = ''
- // to print on top of the user graph if coordinates are not to be printed
- var plotOK = true
- // to flag if there is a valid graph
- var argValues = [];
- // the array of argument values to be passed to the evaluation function
- var coArgValues = [];
- // the array of co-argument values, used in case of contours
- var rangeValues = [];
- // the array of range values received back from the evaluation function. Notice: in case of
- // contours, this is a 2-D array
- var isSlider = false;
- var intSlider = false;
- var rangeValues = [];
- var isSliderArg = false;
- var intSliderArg = false;
- var isSliderCoArg = false;
- var intSliderCoArg = false;
- // it is important to know if (co-) arguments are slides, and if so, if these are all-integer sliders
- //--------------------------------------------------------------------------
- this.moveCallBack = function(x, y, m) {
- if (plotOK) {
- if (m) {
- if (graphContour == 'graph') {
- var h = (x * (argTo - argFrom) + 1 * argFrom) + ' '
- var v = (y * (rangeTo - rangeFrom) + 1 * rangeFrom) + ' '
- h = (h.length > 10) ? h.substr(0, 8) + '...' : h
- v = (v.length > 10) ? v.substr(0, 8) + '...' : v
- $('#userResultPlotLabel').html(argVar + "=" + h + "; " + rangeVar + "=" + v);
- } else {
- // we don't want to re-evaluate the function. Instead, we approximate the
- // function value by bi-linear interpolation from the values in the (2D) range-array
- var h = (x * (argTo - argFrom) + 1 * argFrom)
- var v = (y * (coArgTo - coArgFrom) + 1 * coArgFrom)
- var hhi = Math.max(0.01, Math.min(x * (rangeValues.length - 1), rangeValues.length - 1.01))
- var vvi = Math.max(0.01, Math.min(y * (rangeValues[0].length - 1), rangeValues[0].length - 1.01))
- var hi = Math.floor(hhi)
- var vi = Math.floor(vvi)
- var ll = rangeValues[hi][vi]
- var lh = rangeValues[hi][vi + 1]
- var hl = rangeValues[hi + 1][vi]
- var hh = rangeValues[hi + 1][vi + 1]
- var app = (hhi - hi) * (vvi - vi) * hh + (hi + 1 - hhi) * (vi + 1 - vvi) * ll + (hhi - hi) * (vi + 1 - vvi) * hl + (hi + 1 - hhi) * (vvi - vi) * lh
- h += ' '
- v += ' '
- app += ' '
- h = (h.length > 10) ? h.substr(0, 8) + '...' : h
- v = (v.length > 10) ? v.substr(0, 8) + '...' : v
- app = (app.length > 10) ? app.substr(0, 8) + '...' : app
- $('#userResultPlotLabel').html(argVar + "=" + h + "; " + coArgVar + "=" + v + "; " + rangeVar + "=" + app);
- }
- } else {
- $('#userResultPlotLabel').html(lastFunctionReport);
- }
- }
- }
- //--------------------------------------------------------------------
- this.setRenderMode = function(val) {
- argVar = ''
- coArgVar = ''
- if (val) {
- graphContour = "contour"
- $('#clampControl').hide()
- $('#argVFrom').show()
- $('#argVTo').show()
- $("label[for='graphOrContour']").text("contour");
- $('#userResultPlotLabel').html("Select quantities for contour plot");
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- } else {
- graphContour = "graph"
- $('#clampControl').show()
- $('#argVFrom').hide()
- $('#argVTo').hide()
- $("label[for='graphOrContour']").text("graph");
- $('#userResultPlotLabel').html("Select quantities for contour plot");
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- this.setUpQuantityLists()
- }
- //--------------------------------------------------------------------
- this.setAutoScale = function(val) {
- autoScale = val;
- }
- //---------------------------------------------------------------------
- this.setExactClamp = function(val) {
- exactClamp = val;
- }
- //-----------------------------------------------------
- this.plotUserGraphOrContour = function() {
- if (graphContour == 'graph') {
- that.plotUserGraph()
- } else {
- that.plotUserContour()
- }
- }
- //--------------------------------------------------
- this.plotUserGraph = function() {
- var NRSAMPLES = 50;
- var nrValues;
- argFrom = $('#argFrom').val();
- argTo = $('#argTo').val();
- rangeFrom = $('#rangeFrom').val();
- rangeTo = $('#rangeTo').val();
- var evalOK = true;
- if (!usesHistory() || NITER_SET >= 1) {
- if (myIsNumber(argFrom)) {
- if (myIsNumber(argTo)) {
- if (myIsNumber(rangeFrom)) {
- if (myIsNumber(rangeTo)) {
- if (rangeFrom != rangeTo) {
- if (argFrom != argTo) {
- var argIndex = -1;
- var rangeIndex = -1;
- for (var j = 0; j < symbolTable.length; j++) {
- if (symbolTable[j].name == argVar) {
- argIndex = j;
- var myC1I = symbolTable[j].myCat1Index;
- if (myC1I >= 0) {
- if (cat1Vars[myC1I].type == "slider") {
- isSlider = true;
- if (cat1Vars[myC1I].round) {
- intSlider = true;
- } else {
- intSlider = false
- }
- } else {
- isSlider = false
- }
- } else {
- isSlider = false;
- intSlider = false;
- }
- }
- if (symbolTable[j].name == rangeVar) {
- rangeIndex = j;
- }
- }
- // post condition: argIndex >=0
- msgHasBeenGiven = false;
- if (testReachable(argVar, rangeVar, 0)) {
- if (argIndex >= 0 && rangeIndex >= 0) {
- if (argIndex != rangeIndex) {
- var saveValue = symbolTable[argIndex].valOb;
- // we must not destroy the state prior to drawing the graph
- // it is possible that we have to draw a discrete graph: if the argument is a cat.-I quantity, namely an integer slider
- if (intSlider) {
- var stepSize = 1
- nrValues = argTo - argFrom + 1;
- if (nrValues > 100) {
- stepSize = nrValues / 100
- }
- nrValues = nrValues / stepSize
- var saveSymbol = symbolTable[argIndex].valOb
- for (var i = 0; i < nrValues; i++) {
- symbolTable[argIndex].valOb = 1 * argFrom + 1 * i * stepSize
- // if I don't put the 1*, javascript will concatenate strings !!! GR%$#@#%$@^%$^%@$
- executeOnBehalfOfGraph(argIndex, argIndex)
- argValues[i] = 2.0 + 96.0 * i / (nrValues - 1)
- if (isNumeric(symbolTable[rangeIndex].valOb)) {
- rangeValues[i] = symbolTable[rangeIndex].valOb
- } else {
- rangeValues[i] = -1;
- evalOK = false;
- }
- }
- rangeValues.length = nrValues
- symbolTable[argIndex].valOb = saveSymbol
- } else {
- nrValues = NRSAMPLES
- var saveSymbol = symbolTable[argIndex].valOb
- for (var i = 0; i < NRSAMPLES; i++) {
- var argVal = parseFloat(argFrom) + parseFloat(i * (argTo - argFrom) / (NRSAMPLES - 1));
- symbolTable[argIndex].valOb = argVal;
- executeOnBehalfOfGraph(argIndex, argIndex);
- argValues[i] = 100 * (argVal - argFrom) / (argTo - argFrom);
- if (isNumeric(symbolTable[rangeIndex].valOb)) {
- rangeValues[i] = symbolTable[rangeIndex].valOb
- } else {
- rangeValues[i] = -1;
- evalOK = false;
- }
- }
- rangeValues.length = nrValues
- symbolTable[argIndex].valOb = saveSymbol
- }
- // restore the symbol table
- symbolTable[argIndex].valOb = saveValue;
- // distinguish autoscaling from non autoscaling
- if (autoScale) {
- var minR = rangeValues[0];
- var maxR = rangeValues[0];
- for (i = 0; i < nrValues; i++) {
- if (minR > rangeValues[i])
- minR = rangeValues[i];
- if (maxR < rangeValues[i])
- maxR = rangeValues[i];
- }
- if (exactClamp) {
- var deltaR = (maxR - minR);
- } else {
- var deltaR = 1.1 * (maxR - minR);
- }
- var avg = (maxR + minR) / 2;
- if (exactClamp) {
- if (deltaR == 0) {
- $('#userResultPlotLabel').html("Scaling fails; all computed values = " + avg);
- plotOK = false
- }
- minR = avg - 0.5 * deltaR,
- false;
- maxR = avg + 0.5 * deltaR,
- true;
- } else {
- if (deltaR == 0)
- deltaR = avg;
- minR = niceNumber(avg - 0.5 * deltaR, false);
- maxR = niceNumber(avg + 0.5 * deltaR, true);
- }
- rangeFrom = minR;
- rangeTo = maxR;
- $('#rangeFrom').val(rangeFrom);
- $('#rangeTo').val(rangeTo);
- } else {
- deltaR = rangeTo - rangeFrom;
- }
- if (deltaR > 0) {
- for (i = 0; i < nrValues; i++) {
- rangeValues[i] = 100 * (rangeValues[i] - rangeFrom) / deltaR;
- }
- } else {
- for (i = 0; i < nrValues; i++) {
- rangeValues[i] = 50;
- }
- }
- var plotGraphData = []
- for (i = 0; i < nrValues; i++) {
- plotGraphData.push({
- 'x': argValues[i],
- 'y': rangeValues[i]
- })
- }
- var grid = {
- 'majX': 5,
- 'minX': 21,
- 'grMajX': 'line',
- 'grMinX': 'line',
- 'majY': 5,
- 'minY': 21,
- 'grMajY': 'line',
- 'grMinY': 'line'
- }
- if (!intSlider) {
- var plotGraph = {
- 'grid': grid,
- 'locations': {
- 'data': plotGraphData
- },
- 'edges': {
- 'thickness': 2
- }
- }
- } else {
- var diam = 2;
- if (nrValues < 25)
- diam = 4
- var plotGraph = {
- 'grid': grid,
- 'locations': {
- 'fill': 'interior',
- 'rad': diam / 2,
- 'data': plotGraphData
- }
- }
- }
- if (evalOK) {
- userResultGraph.enforceRedraw()
- userResultGraph.draw([
- plotGraph
- ]);
- lastFunctionReport = rangeVar + ' = function( ' + argVar + ' )'
- $('#userResultPlotLabel').html(lastFunctionReport);
- plotOK = true
- } else {
- alert("one or more of the evaluations failed; we can't plot a graph")
- }
- } else {
- $('#userResultPlotLabel').html("We don't plot identical functions " + rangeVar + " = function( " + argVar + " )");
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("could not find argument and/or range " + argVar + ", " + rangeVar);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html(rangeVar + " does not depend on " + argVar);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("argument from and to values must be different, scanning " + argFrom + " and " + argTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("range from and to values must be different, scanning " + rangeFrom + " and " + rangeTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("range to-value must be a number, scanning " + rangeTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("range from-value must be a number, scanning " + rangeFrom);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("argument to-value must be a number, scanning " + argTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("argument from-value must be a number, scanning " + argFrom);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("cannot draw a graph because model uses time-shift operators ({...}), and iteration counter is set to 0. This means that the model will take infinitely many time steps. Please set the iteration counter to a value >0");
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- }
- //-------------------------------------------------------------------------
- this.plotUserContour = function() {
- var NRSAMPLES = $('#nrContourSamples').val()
- if (NRSAMPLES < 5) {
- NRSAMPLES = 5
- $('#nrContourSamples').val(NRSAMPLES)
- }
- if (NRSAMPLES > 50) {
- NRSAMPLES = 50
- $('#nrContourSamples').val(NRSAMPLES)
- }
- var NRCONTOURS = $('#nrContours').val()
- if (NRCONTOURS < 5) {
- NRCONTOURS = 5
- $('#nrContours').val(NRCONTOURS)
- }
- if (NRCONTOURS > 50) {
- NRCONTOURS = 50
- $('#nrContours').val(NRCONTOURS)
- }
- argFrom = $('#argFrom').val();
- argTo = $('#argTo').val();
- coArgFrom = $('#coArgFrom').val();
- coArgTo = $('#coArgTo').val();
- rangeFrom = $('#rangeFrom').val();
- rangeTo = $('#rangeTo').val();
- var evalOK = true;
- if (!usesHistory() || NITER_SET >= 1) {
- if (myIsNumber(argFrom)) {
- if (myIsNumber(argTo)) {
- if (myIsNumber(coArgFrom)) {
- if (myIsNumber(coArgTo)) {
- if (myIsNumber(rangeFrom)) {
- if (myIsNumber(rangeTo)) {
- if (rangeFrom != rangeTo) {
- if (argFrom != argTo) {
- if (coArgFrom != coArgTo) {
- var argIndex = -1;
- var coArgIndex = -1;
- var rangeIndex = -1;
- for (var j = 0; j < symbolTable.length; j++) {
- if (symbolTable[j].name == argVar) {
- argIndex = j;
- var myC1I = symbolTable[j].myCat1Index;
- if (myC1I >= 0) {
- if (cat1Vars[myC1I].type == "slider") {
- isSliderArg = true;
- if (cat1Vars[myC1I].round) {
- intSliderArg = true;
- } else {
- intSliderArg = false
- }
- } else {
- isSliderArg = false
- }
- } else {
- isSliderArg = false;
- intSliderArg = false;
- }
- }
- if (symbolTable[j].name == coArgVar) {
- coArgIndex = j;
- var myC1I = symbolTable[j].myCat1Index;
- if (myC1I >= 0) {
- if (cat1Vars[myC1I].type == "slider") {
- isSliderCoArg = true;
- if (cat1Vars[myC1I].round) {
- intSliderCoArg = true;
- } else {
- intSliderCoArg = false
- }
- } else {
- isSliderCoArg = false
- }
- } else {
- isSliderCoArg = false;
- intSliderCoArg = false;
- }
- }
- if (symbolTable[j].name == rangeVar) {
- rangeIndex = j;
- }
- }
- // post condition: argIndex >=0 and coArgIndex >=0
- msgHasBeenGiven = false;
- if (testReachable(argVar, rangeVar, 0)) {
- if (testReachable(coArgVar, rangeVar, 0)) {
- if (argIndex >= 0 && rangeIndex >= 0 && coArgIndex >= 0) {
- if ((argIndex != rangeIndex) && (coArgIndex != rangeIndex)) {
- var saveValue = symbolTable[argIndex].valOb;
- var coSaveValue = symbolTable[coArgIndex].valOb
- for (var i = 0; i < NRSAMPLES; i++) {
- if (intSliderArg) {
- argValues[i] = 1 * argFrom + i * (argTo - argFrom) / (NRSAMPLES - 1)
- argValues[i] = Math.round(argValues[i])
- } else {
- argValues[i] = 1 * argFrom + i * (argTo - argFrom) / (NRSAMPLES - 1)
- }
- }
- for (i = 0; i < NRSAMPLES; i++) {
- if (intSliderCoArg) {
- coArgValues[i] = 1 * coArgFrom + i * (coArgTo - coArgFrom) / (NRSAMPLES - 1)
- coArgValues[i] = Math.round(coArgValues[i])
- } else {
- coArgValues[i] = 1 * coArgFrom + i * (coArgTo - coArgFrom) / (NRSAMPLES - 1)
- }
- }
- if (autoScale) {
- var minR = 9.9e+100
- var maxR = -9.9e+100
- } else {
- var minR = $('#rangeFrom').val()
- var maxR = $('#rangeTo').val()
- }
- for (i = 0; i < NRSAMPLES; i++) {
- rangeValues[i] = []
- for (j = 0; j < NRSAMPLES; j++) {
- symbolTable[argIndex].valOb = argValues[i]
- symbolTable[coArgIndex].valOb = coArgValues[j]
- executeOnBehalfOfGraph(argIndex, coArgIndex)
- if (isNumeric(symbolTable[rangeIndex].valOb)) {
- rangeValues[i].push(symbolTable[rangeIndex].valOb)
- } else {
- rangeValues[i].push(-1)
- evalOK = false
- }
- if (rangeValues[i][j] < minR && autoScale) {
- minR = rangeValues[i][j]
- }
- if (rangeValues[i][j] > maxR && autoScale) {
- maxR = rangeValues[i][j]
- }
- }
- }
- rangeValues.length = NRSAMPLES
- // this is necessary, because the same array is used in the draw graph-case,
- // and then rangeValues could have received more than NRSAMPLES values.
- if (autoScale) {
- $('#rangeFrom').val(minR);
- $('#rangeTo').val(maxR);
- }
- symbolTable[argIndex].valOb = saveValue
- symbolTable[coArgIndex].valOb = coSaveValue
- executeOnBehalfOfGraph(argIndex, coArgIndex)
- var grid = {
- 'majX': 5,
- 'minX': 21,
- 'grMajX': 'line',
- 'grMinX': 'line',
- 'majY': 5,
- 'minY': 21,
- 'grMajY': 'line',
- 'grMinY': 'line'
- }
- var plotContour = {
- 'grid': grid,
- 'contour': {
- 'nrContours': NRCONTOURS,
- 'map': rangeValues,
- 'iso': {
- 'mode': 'intp',
- 'low': minR,
- 'high': maxR
- },
- 'col_r': {
- 'mode': 'intp',
- 'low': 0,
- 'high': 255
- }
- }
- }
- if (evalOK) {
- userResultGraph.enforceRedraw()
- userResultGraph.draw([plotContour]);
- lastFunctionReport = rangeVar + ' = function( ' + argVar + ',' + coArgVar + ' )'
- $('#userResultPlotLabel').html(lastFunctionReport);
- plotOK = true
- } else {
- alert("one or more of the evaluations failed; we can't plot a graph")
- plotOK = false
- }
- } else {
- $('#userResultPlotLabel').html("We don't plot identical functions " + rangeVar + " = function( " +
- argVar + " ) and/or " + rangeVar + " = function( " + coArgVar + ")");
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("could not find hor. argument and/or vert. argument and/or range " + argVar + ", " + coArgVar + "," + rangeVar);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html(rangeVar + " does not depend on " + coArgVar);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html(rangeVar + " does not depend on " + argVar);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("vertical argument from and to values must be different, scanning " + coArgFrom + " and " + coAgTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("horizontal argument from and to values must be different, scanning " + argFrom + " and " + argTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("range from and to values must be different, scanning " + rangeFrom + " and " + rangeTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("range to-value must be a number, scanning " + rangeTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("range from-value must be a number, scanning " + rangeFrom);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("vertical argument to-value must be a number, scanning " + coArgTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("vertical argument from-value must be a number, scanning " + coArgFrom);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("horizontal argument to-value must be a number, scanning " + argTo);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("horizontal argument from-value must be a number, scanning " + argFrom);
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- } else {
- $('#userResultPlotLabel').html("cannot draw a graph because model uses time-shift operators ({...}), and iteration counter is set to 0. This means that the model will take infinitely many time steps. Please set the iteration counter to a value >0");
- plotOK = false
- userResultGraph.draw([
- wrongGraph
- ]);
- }
- }
- //--------------------------------------------------------------------------
- this.eraseState = function() {
- // this is called when the script is (re) compiled, so any quantitiy selections made earlier
- // loose their meaning
- rememberState = false;
- $('#userResultPlotLabel').html("");
- plotOK = false
- $('#argFrom').html("");
- $('#argTo').html("");
- $('#coArgFrom').html("");
- $('#coArgTo').html("");
- $('#rangeFrom').html("");
- $('#rangeTo').html("");
- }
- //-------------------------------------------------------------------------
- this.optionalRefresh = function() {
- // in case there were quantities selected the previous time this tab
- // was visible, and the script has not changed, it is possible that
- // cat.-I quantities have changed. In that case we must update the graph
- if (rememberState) {
- if (graphContour == 'graph') {
- that.plotUserGraph()
- } else {
- that.plotUserContour()
- }
- }
- }
- //-------------------------------------------------------------------------
- this.setUpQuantityLists = function() {
- userPlotArg = [];
- userPlotRange = [];
- for (var i = 0; i < symbolTable.length; i++) {
- if (!symbolTable[i].isDummy) {
- if (!isUserFunction(symbolTable[i].name)) {
- if (!(symbolTable[i].valOb instanceof Array)) {
- if (myIsNumber(symbolTable[i].valOb)) {
- userPlotArg.push({
- 'name': symbolTable[i].name,
- 'value': symbolTable[i].valOb.toPrecision ? symbolTable[i].valOb.toPrecision(2) : symbolTable[i].valOb,
- // in case valOb is a string, it doesn't make sense to ask for the first two digits
- 'horPlot': (symbolTable[i].name == argVar) ? 'H' : '_',
- 'verPlot': (symbolTable[i].name == coArgVar) ? 'V' : '_'
- });
- userPlotRange.push({
- 'name': symbolTable[i].name,
- 'value': symbolTable[i].valOb.toPrecision ? symbolTable[i].valOb.toPrecision(2) : symbolTable[i].valOb
- });
- }
- }
- }
- }
- }
- userPlotArg.sort(varSorter);
- userPlotRange.sort(varSorter);
- var plotArgFormat = []
- if (graphContour == 'graph') {
- plotArgFormat.push({
- bd: 'name',
- bf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#cccccc"',
- hd: 'name',
- tt: 'name of the quantity',
- hf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#ffffff"',
- bc: function(data, row) {
- if (data[row]['value'] != 0) {
- $('#argFrom').val(0.5 * data[row]['value']);
- $('#argTo').val(2.0 * data[row]['value']);
- } else {
- $('#argFrom').val(-1);
- $('#argTo').val(1);
- }
- argVar = data[row]['name'];
- // if the clicked arg-quantity happens to be in cat.-I, and if it happens to be a slider,
- // we take the lower and upper bounds of the slider as from- and to values.
- for (var j = 0; j < symbolTable.length; j++) {
- if (symbolTable[j].name == argVar) {
- var myC1I = symbolTable[j].myCat1Index;
- if (myC1I >= 0) {
- if (cat1Vars[myC1I].type == "slider") {
- $('#argFrom').val(cat1Vars[myC1I].low);
- $('#argTo').val(cat1Vars[myC1I].high);
- }
- }
- }
- }
- autoScale = true;
- rememberState = true;
- that.plotUserGraphOrContour();
- }
- })
- } else {
- plotArgFormat.push({
- bd: 'name',
- bf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#cccccc"',
- hd: 'name',
- tt: 'name of the quantity',
- hf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#ffffff"',
- bc: function(data, row) {
- alert("You must click on the 'H' or the 'V' column to assign quantity <" + data[row]['name'] + "> to the horizontal or vertical axis of the contour plot, respectively")
- }
- })
- }
- plotArgFormat.push({
- bd: function() {
- return '?'
- },
- bf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#00cc00;text-decoration:underline;"',
- hd: '?',
- tt: 'the comment (explanation) of this quantity',
- hf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#ffffff"',
- bc: function(data, row) {
- var k = 0;
- var fnd = false;
- while (!fnd && k < script.length) {
- if (script[k].varName == data[row]['name']) {
- fnd = true;
- if (script[k].comment) {
- alert(script[k].comment);
- } else {
- alert("could not find comment text for quantity " + data[row]['name']);
- }
- } else {
- k++;
- }
- }
- if (!fnd)
- alert("could not find quantity " + data[row]['name']);
- }
- })
- plotArgFormat.push({
- bd: 'value',
- bf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#00ffff"',
- hd: 'value',
- tt: 'the value for this quantity',
- hf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#ffffff"'
- })
- if (graphContour == 'contour') {
- plotArgFormat.push({
- bd: 'horPlot',
- bf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#00cc00;text-decoration:underline;"',
- hd: 'H',
- tt: 'select this quantity for plotting horizontally in the contour plot',
- hf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#ffffff"',
- bc: function(data, row) {
- argVar = data[row]['name']
- that.setUpQuantityLists()
- if (data[row]['value'] != 0) {
- $('#argFrom').val(0.5 * data[row]['value']);
- $('#argTo').val(2.0 * data[row]['value']);
- } else {
- $('#argFrom').val(-1);
- $('#argTo').val(1);
- }
- // if the clicked arg-quantity happens to be in cat.-I, and if it happens to be a slider,
- // we take the lower and upper bounds of the slider as from- and to values.
- for (var j = 0; j < symbolTable.length; j++) {
- if (symbolTable[j].name == argVar) {
- var myC1I = symbolTable[j].myCat1Index;
- if (myC1I >= 0) {
- if (cat1Vars[myC1I].type == "slider") {
- $('#argFrom').val(cat1Vars[myC1I].low);
- $('#argTo').val(cat1Vars[myC1I].high);
- }
- }
- }
- }
- autoScale = true;
- rememberState = true;
- that.plotUserGraphOrContour();
- }
- })
- plotArgFormat.push({
- bd: 'verPlot',
- bf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#00cc00;text-decoration:underline;"',
- hd: 'V',
- tt: 'select this quantity for plotting vertically in the contour plot',
- hf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#ffffff"',
- bc: function(data, row) {
- coArgVar = data[row]['name']
- that.setUpQuantityLists()
- if (data[row]['value'] != 0) {
- $('#coArgFrom').val(0.5 * data[row]['value']);
- $('#coArgTo').val(2.0 * data[row]['value']);
- } else {
- $('#coArgFrom').val(-1);
- $('#coArgTo').val(1);
- }
- // if the clicked arg-quantity happens to be in cat.-I, and if it happens to be a slider,
- // we take the lower and upper bounds of the slider as from- and to values.
- for (var j = 0; j < symbolTable.length; j++) {
- if (symbolTable[j].name == coArgVar) {
- var myC1I = symbolTable[j].myCat1Index;
- if (myC1I >= 0) {
- if (cat1Vars[myC1I].type == "slider") {
- $('#coArgFrom').val(cat1Vars[myC1I].low);
- $('#coArgTo').val(cat1Vars[myC1I].high);
- }
- }
- }
- }
- autoScale = true;
- rememberState = true;
- that.plotUserGraphOrContour();
- }
- })
- }
- userPlotArgsList.drawTable(userPlotArg, plotArgFormat);
- userPlotRangesList.drawTable(userPlotRange, [{
- bd: 'name',
- bf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#cccccc"',
- hd: 'name',
- tt: 'the name of this quantity',
- hf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#ffffff"',
- bc: function(data, row) {
- if (data[row]['value'] != 0) {
- $('#rangeFrom').val(0.5 * data[row]['value']);
- $('#rangeTo').val(2.0 * data[row]['value']);
- } else {
- $('#rangeFrom').val(-1);
- $('#rangeTo').val(1);
- }
- rangeVar = data[row]['name'];
- this.autoScale = true;
- that.plotUserGraphOrContour();
- }
- }, {
- bd: function() {
- return '?'
- },
- bf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#00cc00;text-decoration:underline;"',
- hd: '?',
- tt: 'the comment (explanation) of this quantity',
- hf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#ffffff"',
- bc: function(data, row) {
- var k = 0;
- var fnd = false;
- while (!fnd && k < script.length) {
- if (script[k].varName == data[row]['name']) {
- fnd = true;
- if (script[k].comment) {
- alert(script[k].comment);
- } else {
- alert("could not find comment text for quantity " + data[row]['name']);
- }
- } else {
- k++;
- }
- }
- if (!fnd)
- alert("could not find quantity " + data[row]['name']);
- }
- }, {
- bd: 'value',
- bf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#00ffff"',
- hd: 'value',
- tt: 'the value for this quantity',
- hf: 'style=" text-align: left;font-family:Verdana;font-size:60%;color:#ffffff"'
- }]);
- }
- //-------------------------------------------------
- var varSorter = function(a, b) {
- return (a.name > b.name ? 1 : (a.name < b.name ? -1 : 0));
- }
- //------------------------------------------------------------------------------------------------------------------
- var testReachable = function(argVar, rangeVar, cnter) {
- for (var i = 0; i < symbolTable.length; i++) {
- symbolTable[i].touched = false;
- }
- var result = reachable(argVar, rangeVar, cnter)
- for (i = 0; i < symbolTable.length; i++) {
- symbolTable[i].touched = false;
- }
- return result
- }
- //-------------------------------------------------------------------------------------------------------------------
- var reachable = function(argVar, rangeVar, cnter) {
- // return true if the rangeVar depends on the argVar. Do a recursive connectivity search in the depOn-arrays in the symboltable entries, starting
- // in rangeVar.
- if (cnter > script.length) {
- if (!msgHasBeenGiven) {
- alert("Cannot assess if quantity " + rangeVar + " depends on quantity " + argVar + ". Perhaps there is a cyclic dependency in the model.")
- msgHasBeenGiven = true
- }
- return false
- }
- var iRangeIndex = findSymbolTableEntryPoint(rangeVar);
- if (!symbolTable[iRangeIndex].touched) {
- var isReachable = false;
- var i = 0;
- if (argVar == rangeVar)
- return true;
- while (i < symbolTable[iRangeIndex].depOn.length && !isReachable) {
- symbolTable[iRangeIndex].touched = true
- if (reachable(argVar, symbolTable[iRangeIndex].depOn[i].name, cnter + 1)) {
- isReachable = true;
- } else {
- i++;
- }
- }
- } else {
- return false
- }
- return isReachable;
- }
- //------------------------------------------------------------------------------------------------------------------
- var executeOnBehalfOfGraph = function(p1, p2) {
- shouldCheckUnits = false
- if (NITER_SET == 0) {
- for (var k = 0; k < symbolTable.length; k++) {
- if (k == p1 || k == p2) {
- symbolTable[k].eval = true;
- } else {
- symbolTable[k].eval = false;
- }
- }
- rt.execute(false, false);
- } else {
- // now we cannot use rt.execute, since we need to keep the symboltable value with index p the same.
- // So we have to do the main part of preruninitialization and iterating over NITER_SET loops ourselves.
- var nIter = 0;
- rt.clearHistories();
- while (nIter < NITER_SET) {
- var i = 0;
- while (i < symbolTable.length) {
- if (i != p1 && i != p2) {
- if (symbolTable[i].valOb instanceof Array) {
- symbolTable[i].valOb = [];
- } else {
- symbolTable[i].valOb = 0;
- }
- symbolTable[i].eval = false;
- } else {
- symbolTable[i].eval = true;
- }
- symbolTable[i].touched = false;
- i++;
- }
- rt.executeOnceBare();
- nIter++;
- }
- }
- }
- //--------------------------------------------------
- var myIsNumber = function(n) {
- return !isNaN(parseFloat(n)) && isFinite(n);
- }
- }
- //--------------------------------------------------------------
- var usesHistory = function() {
- var useHis = false
- for (var i = 0; i < symbolTable.length; i++) {
- if (symbolTable[i].dValOb.length > 0) {
- useHis = true;
- }
- }
- return useHis
- }
- //-------------------------------------------------------------
- var niceNumber = function(p, dir) {
- // clips p to a nearest number with no more than 2 non-zero decimals.
- // If dir==false round down, otherwise round up.
- var q = Math.abs(p);
- var nDec = Math.round(Math.log(q) / 2.302585092994046);
- var refN = Math.pow(10, nDec);
- if (dir) {
- var reduced = refN * Math.ceil(10 * q / refN) / 10;
- } else {
- var reduced = refN * Math.floor(10 * q / refN) / 10;
- }
- if (p < 0) {
- return -reduced;
- } else {
- return reduced;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement