Skip to content

Commit

Permalink
Merge pull request #538 from highperformancecoder/feature-256-summary…
Browse files Browse the repository at this point in the history
…-tab

Feature 256 summary tab
  • Loading branch information
highperformancecoder authored Dec 30, 2024
2 parents 2afa39f + 934a03d commit daaa08f
Show file tree
Hide file tree
Showing 24 changed files with 317 additions and 439 deletions.
2 changes: 1 addition & 1 deletion engine/equations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ namespace MathDAG
{
// slightly convoluted to prevent sliderSet from overriding c->value
iv->init(c->value);
iv->adjustSliderBounds();
if (auto vv=iv->vValue()) vv->adjustSliderBounds();
}
else
throw error("only constants, parameters and variables can be connected to the initial value port");
Expand Down
33 changes: 17 additions & 16 deletions engine/mdlReader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -366,24 +366,25 @@ namespace minsky
}
catch (...) {}
v->detailedText(comments);
if (regex_match(sliderSpec,match,sliderSpecPattern))
if (auto vv=v->vValue())
{
vector<string> spec;
for (size_t i=1; i<=match.size(); ++i) spec.push_back(match[i]);
if (!spec.empty() && regex_match(spec[0],match,number))
v->sliderMin=stod(spec[0]);
else
v->sliderMin=0.1*stod(definition);
if (spec.size()>1 && regex_match(spec[1],match,number))
v->sliderMax=stod(spec[1]);
else
v->sliderMax=10*stod(definition);
if (spec.size()>2 && regex_match(spec[2],match,number))
v->sliderStep=stod(spec[2]);
v->adjustSliderBounds();
if (regex_match(sliderSpec,match,sliderSpecPattern))
{
vector<string> spec;
for (size_t i=1; i<=match.size(); ++i) spec.push_back(match[i]);
if (!spec.empty() && regex_match(spec[0],match,number))
vv->sliderMin=stod(spec[0]);
else
vv->sliderMin=0.1*stod(definition);
if (spec.size()>1 && regex_match(spec[1],match,number))
vv->sliderMax=stod(spec[1]);
else
vv->sliderMax=10*stod(definition);
if (spec.size()>2 && regex_match(spec[2],match,number))
vv->sliderStep=stod(spec[2]);
}
vv->adjustSliderBounds();
}
else
v->initSliderBounds();
}
else
{
Expand Down
12 changes: 9 additions & 3 deletions model/slider.h → engine/slider.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,18 @@ namespace minsky
/// operations and variables
struct Slider
{
mutable bool sliderBoundsSet=false, ///< slider bounds have been initialised at some point
sliderStepRel=false; /**< sliderStep is relative to the range
bool sliderStepRel=false; /**< sliderStep is relative to the range
[sliderMin,sliderMax] */

mutable double sliderMin, sliderMax, sliderStep;
double sliderMin=std::numeric_limits<double>::max(),
sliderMax=-sliderMin, sliderStep=0;
bool enableSlider=true;

/// ensure there are at most 10000 steps between sliderMin and Max. see ticket 1255.
double maxSliderSteps() const {
if (!isfinite(sliderStep) || sliderMax-sliderMin > 1.0e04*sliderStep) return (sliderMax-sliderMin)/1.0e04;
return sliderStep;
}
};
}

Expand Down
1 change: 1 addition & 0 deletions engine/variableSummary.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ namespace minsky
std::string definition; ///< LaTeXable definition
std::string udfDefinition; ///< use function compatible definition
std::string init; ///< initial value
double sliderStep, sliderMin, sliderMax; ///< slider parameters
double value=nan(""); ///< value, if scalar
std::string scope; ///< name, id of scope if local, ":" if global
std::string godley; ///< name or id of Godley table, if contained in a Godley table
Expand Down
77 changes: 53 additions & 24 deletions engine/variableValue.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "index.rcd"
#include "index.xcd"
#include "nobble.h"
#include "slider.rcd"
#include "tensorInterface.rcd"
#include "tensorInterface.xcd"
#include "tensorVal.rcd"
Expand Down Expand Up @@ -214,10 +215,37 @@ namespace minsky
if (rhs) return rhs->hypercube();
// return the initialisation hypercube if not a defined flowVar
if (tensorInit.rank()>0 && (!isFlowVar() || m_type==parameter || !cminsky().definingVar(valueId())))
return tensorInit.hypercube();
return tensorInit.hypercube();
return m_hypercube;
}

void VariableValue::sliderSet(double x)
{
if (!isfinite(x)) return;
if (x<sliderMin) x=sliderMin;
if (x>sliderMax) x=sliderMax;
sliderStep=maxSliderSteps();
init(to_string(x));
setValue(x);
}

void VariableValue::incrSlider(double step)
{
sliderSet(value()+step*(sliderStepRel? value(): 1)*sliderStep);
}

void VariableValue::adjustSliderBounds()
{
if (size()==1 && !isnan(value()))
{
if (!finite(sliderMax) ||sliderMax<value())
sliderMax=value()? abs(10*value()):1;
if (!finite(sliderMin) || sliderMin>=value())
sliderMin=value()? -abs(10*value()):-1;
assert(sliderMin<sliderMax);
sliderStep=maxSliderSteps();
}
}


TensorVal VariableValues::initValue
Expand Down Expand Up @@ -245,7 +273,7 @@ namespace minsky
if (tmp>0 && e>x && *e)
{
x=e+1;
dims.push_back(tmp);
dims.push_back(tmp);
}
else
break;
Expand Down Expand Up @@ -300,27 +328,27 @@ namespace minsky
void VariableValues::resetValue(VariableValue& v) const
{
if (v.idx()<0) v.allocValue();
// initialise variable only if its variable is not defined or it is a stock
if (!v.isFlowVar() || !cminsky().definingVar(v.valueId()))
{
if (v.tensorInit.rank())
{
// ensure dimensions are correct
auto hc=v.tensorInit.hypercube();
for (auto& xv: hc.xvectors)
{
auto dim=cminsky().dimensions.find(xv.name);
if (dim!=cminsky().dimensions.end())
xv.dimension=dim->second;
}
v.tensorInit.hypercube(hc);
}
if (v.tensorInit.rank())
v=v.tensorInit;
else
v=initValue(v);
}
assert(v.idxInRange());
// initialise variable only if its variable is not defined or it is a stock
if (!v.isFlowVar() || !cminsky().definingVar(v.valueId()))
{
if (v.tensorInit.rank())
{
// ensure dimensions are correct
auto hc=v.tensorInit.hypercube();
for (auto& xv: hc.xvectors)
{
auto dim=cminsky().dimensions.find(xv.name);
if (dim!=cminsky().dimensions.end())
xv.dimension=dim->second;
}
v.tensorInit.hypercube(hc);
}
if (v.tensorInit.rank())
v=v.tensorInit;
else
v=initValue(v);
}
assert(v.idxInRange());
}


Expand All @@ -344,7 +372,7 @@ namespace minsky
resetValue(v.second->allocValue());
assert(v.second->idxInRange());
}
}
}

bool VariableValues::validEntries() const
{
Expand Down Expand Up @@ -533,6 +561,7 @@ namespace minsky
definition,
udfDefinition,
init(),
sliderStep, sliderMin, sliderMax,
value(),
scopeName,
godleyName,
Expand Down
13 changes: 10 additions & 3 deletions engine/variableValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "str.h"
#include "CSVDialog.h"
#include "latexMarkup.h"
#include "slider.h"
#include "valueId.h"
#include "variableSummary.h"
#include <regex>
Expand All @@ -41,7 +42,7 @@ namespace minsky
typedef std::shared_ptr<Group> GroupPtr;
using namespace civita;

struct VariableValueData: public civita::ITensorVal
struct VariableValueData: public civita::ITensorVal, public Slider
{
using ITensorVal::operator=;

Expand All @@ -58,8 +59,6 @@ namespace minsky
/// long and short descriptions - common to all variables of a given name
std::string detailedText, tooltip;


bool sliderVisible=false; // determined at reset time
bool godleyOverridden=false;
std::string name; // name of this variable
classdesc::Exclude<std::weak_ptr<Group>> m_scope;
Expand Down Expand Up @@ -186,6 +185,14 @@ namespace minsky

const std::string& init() const {return m_init;}
const std::string& init(const std::string& x);

/// sets variable value (or init value)
void sliderSet(double x);
/// increment slider by \a step
void incrSlider(double step);

/// adjust slider bounds to encompass the current value
void adjustSliderBounds();
};

struct ValueVector
Expand Down
24 changes: 14 additions & 10 deletions gui-js/libs/shared/src/lib/backend/minsky.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ export class VariableBase extends Item {
async drawSelected(a1: minsky__dummy): Promise<void> {return this.$callMethod('drawSelected',a1);}
async dummyDraw(): Promise<void> {return this.$callMethod('dummyDraw');}
async editorMode(): Promise<boolean> {return this.$callMethod('editorMode');}
async enableSlider(...args: boolean[]): Promise<boolean> {return this.$callMethod('enableSlider',...args);}
async enableSlider(...args: any[]): Promise<boolean> {return this.$callMethod('enableSlider',...args);}
async engExp(): Promise<object> {return this.$callMethod('engExp');}
async ensureBBValid(): Promise<void> {return this.$callMethod('ensureBBValid');}
async ensureValueExists(a1: VariableValue,a2: string): Promise<void> {return this.$callMethod('ensureValueExists',a1,a2);}
Expand All @@ -245,7 +245,6 @@ export class VariableBase extends Item {
async importFromCSV(a1: string,a2: DataSpecSchema): Promise<void> {return this.$callMethod('importFromCSV',a1,a2);}
async inItem(a1: number,a2: number): Promise<boolean> {return this.$callMethod('inItem',a1,a2);}
async init(...args: any[]): Promise<string> {return this.$callMethod('init',...args);}
async initSliderBounds(): Promise<void> {return this.$callMethod('initSliderBounds');}
async inputWired(): Promise<boolean> {return this.$callMethod('inputWired');}
async ioVar(): Promise<boolean> {return this.$callMethod('ioVar');}
async isStock(): Promise<boolean> {return this.$callMethod('isStock');}
Expand All @@ -259,7 +258,6 @@ export class VariableBase extends Item {
async m_y(...args: number[]): Promise<number> {return this.$callMethod('m_y',...args);}
async makeConsistentWithValue(): Promise<void> {return this.$callMethod('makeConsistentWithValue');}
async mantissa(a1: EngNotation,a2: number): Promise<string> {return this.$callMethod('mantissa',a1,a2);}
async maxSliderSteps(): Promise<number> {return this.$callMethod('maxSliderSteps');}
async miniPlotEnabled(...args: any[]): Promise<boolean> {return this.$callMethod('miniPlotEnabled',...args);}
async mouseFocus(...args: boolean[]): Promise<boolean> {return this.$callMethod('mouseFocus',...args);}
async moveTo(a1: number,a2: number): Promise<void> {return this.$callMethod('moveTo',a1,a2);}
Expand Down Expand Up @@ -293,12 +291,10 @@ export class VariableBase extends Item {
async selected(...args: boolean[]): Promise<boolean> {return this.$callMethod('selected',...args);}
async setDimLabelsPicked(a1: string,a2: string): Promise<object> {return this.$callMethod('setDimLabelsPicked',a1,a2);}
async setUnits(a1: string): Promise<void> {return this.$callMethod('setUnits',a1);}
async sliderBoundsSet(...args: boolean[]): Promise<boolean> {return this.$callMethod('sliderBoundsSet',...args);}
async sliderMax(...args: number[]): Promise<number> {return this.$callMethod('sliderMax',...args);}
async sliderMin(...args: number[]): Promise<number> {return this.$callMethod('sliderMin',...args);}
async sliderSet(a1: number): Promise<void> {return this.$callMethod('sliderSet',a1);}
async sliderStep(...args: number[]): Promise<number> {return this.$callMethod('sliderStep',...args);}
async sliderStepRel(...args: boolean[]): Promise<boolean> {return this.$callMethod('sliderStepRel',...args);}
async sliderMax(...args: any[]): Promise<number> {return this.$callMethod('sliderMax',...args);}
async sliderMin(...args: any[]): Promise<number> {return this.$callMethod('sliderMin',...args);}
async sliderStep(...args: any[]): Promise<number> {return this.$callMethod('sliderStep',...args);}
async sliderStepRel(...args: any[]): Promise<boolean> {return this.$callMethod('sliderStepRel',...args);}
async sliderVisible(): Promise<boolean> {return this.$callMethod('sliderVisible');}
async temp(): Promise<boolean> {return this.$callMethod('temp');}
async throw_error(a1: string): Promise<void> {return this.$callMethod('throw_error',a1);}
Expand Down Expand Up @@ -2282,25 +2278,29 @@ export class VariableValue extends CppClass {
this.tensorInit=new civita__TensorVal(this.$prefix()+'.tensorInit');
this.units=new Units(this.$prefix()+'.units');
}
async adjustSliderBounds(): Promise<void> {return this.$callMethod('adjustSliderBounds');}
async allocValue(): Promise<VariableValue> {return this.$callMethod('allocValue');}
async at(a1: number): Promise<number> {return this.$callMethod('at',a1);}
async atHCIndex(a1: number): Promise<number> {return this.$callMethod('atHCIndex',a1);}
async begin(): Promise<number> {return this.$callMethod('begin');}
async cancel(a1: boolean): Promise<void> {return this.$callMethod('cancel',a1);}
async data(): Promise<number[]> {return this.$callMethod('data');}
async detailedText(...args: string[]): Promise<string> {return this.$callMethod('detailedText',...args);}
async enableSlider(...args: boolean[]): Promise<boolean> {return this.$callMethod('enableSlider',...args);}
async end(): Promise<number> {return this.$callMethod('end');}
async exportAsCSV(a1: string,a2: string,a3: boolean): Promise<void> {return this.$callMethod('exportAsCSV',a1,a2,a3);}
async godleyOverridden(...args: boolean[]): Promise<boolean> {return this.$callMethod('godleyOverridden',...args);}
async hypercube(...args: any[]): Promise<civita__Hypercube> {return this.$callMethod('hypercube',...args);}
async idx(): Promise<number> {return this.$callMethod('idx');}
async idxInRange(): Promise<boolean> {return this.$callMethod('idxInRange');}
async imposeDimensions(a1: Container<Pair<string,civita__Dimension>>): Promise<void> {return this.$callMethod('imposeDimensions',a1);}
async incrSlider(a1: number): Promise<void> {return this.$callMethod('incrSlider',a1);}
async index(...args: any[]): Promise<civita__Index> {return this.$callMethod('index',...args);}
async init(...args: any[]): Promise<string> {return this.$callMethod('init',...args);}
async isFlowVar(): Promise<boolean> {return this.$callMethod('isFlowVar');}
async isZero(): Promise<boolean> {return this.$callMethod('isZero');}
async lhs(): Promise<boolean> {return this.$callMethod('lhs');}
async maxSliderSteps(): Promise<number> {return this.$callMethod('maxSliderSteps');}
async name(...args: string[]): Promise<string> {return this.$callMethod('name',...args);}
async rank(): Promise<number> {return this.$callMethod('rank');}
async reset_idx(): Promise<void> {return this.$callMethod('reset_idx');}
Expand All @@ -2310,7 +2310,11 @@ export class VariableValue extends CppClass {
async setValue(...args: any[]): Promise<number> {return this.$callMethod('setValue',...args);}
async shape(): Promise<number[]> {return this.$callMethod('shape');}
async size(): Promise<number> {return this.$callMethod('size');}
async sliderVisible(...args: boolean[]): Promise<boolean> {return this.$callMethod('sliderVisible',...args);}
async sliderMax(...args: number[]): Promise<number> {return this.$callMethod('sliderMax',...args);}
async sliderMin(...args: number[]): Promise<number> {return this.$callMethod('sliderMin',...args);}
async sliderSet(a1: number): Promise<void> {return this.$callMethod('sliderSet',a1);}
async sliderStep(...args: number[]): Promise<number> {return this.$callMethod('sliderStep',...args);}
async sliderStepRel(...args: boolean[]): Promise<boolean> {return this.$callMethod('sliderStepRel',...args);}
async summary(): Promise<object> {return this.$callMethod('summary');}
async temp(): Promise<boolean> {return this.$callMethod('temp');}
async tooltip(...args: string[]): Promise<string> {return this.$callMethod('tooltip',...args);}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export class CreateVariableComponent implements OnInit, OnDestroy {
saveVariableParams(item: VariableBase) {
item.setUnits(this.units.value || '');
item.init(this.value.value);
item.initSliderBounds(); // ensure slider bounds starts with a reasonable value
item.adjustSliderBounds(); // ensure slider bounds starts with a reasonable value
item.rotation(this.rotation.value || 0);
item.tooltip(this.shortDescription.value);
item.detailedText(this.detailedDescription.value);
Expand Down
Loading

0 comments on commit daaa08f

Please sign in to comment.