Commit b5fbb0e9 authored by Mathias Chouet's avatar Mathias Chouet :spaghetti:
Browse files

[WIP] work on #62adapted CalcSerie() to multiple varying parametersremoved...

[WIP] work on #62adapted CalcSerie() to multiple varying parametersremoved valueMode constraint on max. 1 variated parameteradded jasmine tests
parent dae6be04
No related merge requests found
Showing with 486 additions and 252 deletions
+486 -252
......@@ -141,17 +141,12 @@ function createEnv() {
function checkConsistency(nubToCheck: Nub) {
expect(nubToCheck.calculatedParam).toBeDefined();
let calcCount = 0;
let varCount = 0;
for (const p of nubToCheck.parameterIterator) {
if (p.valueMode === ParamValueMode.CALCUL) {
calcCount++;
}
if (p.valueMode === ParamValueMode.MINMAX || p.valueMode === ParamValueMode.LISTE) {
varCount++;
}
}
expect(calcCount).toBe(1);
expect(varCount).toBeLessThanOrEqual(1);
nubToCheck.CalcSerie();
expect(nubToCheck.result).toBeDefined();
......@@ -232,8 +227,7 @@ describe("cohérence des modes de paramètres : ", () => {
testModesPermutations(nub2);
});
// @TODO reenable after fixing jalhyd#74
xit("ouvrages en parallèle : Cloisons", () => {
it("ouvrages en parallèle : Cloisons", () => {
createEnv();
testModesPermutations(nub3);
});
......
import { CreateStructure, ExtensionStrategy, LoiDebit, ParallelStructure, ParallelStructureParams,
ParamValueMode, Structure} from "../../src/index";
import { RectangularStructureParams } from "../../src/structure/structure_cem88d";
let prms1: ParallelStructureParams;
let nub1: ParallelStructure;
let struct1: Structure;
let prmsStruct: RectangularStructureParams;
function createSingleNubEnv() {
prms1 = new ParallelStructureParams(0.5, 102, 101.5);
nub1 = new ParallelStructure(prms1);
struct1 = CreateStructure(LoiDebit.Cunge80, nub1);
prmsStruct = struct1.prms as RectangularStructureParams;
nub1.addChild(struct1);
}
function createLinkedNubEnv() {
// TODO
}
/**
* Generates a random-length list of numbers close
* @param refVal reference value
* @param minSize minimum size of the list to be returned
* @param maxSize maximum size of the list to be returned
* @param maxDev maximum deviation, so that generated numbers
* value v verifies (refVal - maxDev) < v < (refVal + maxDev)
* @param sort if true, list will be ordered
*/
function randomList(
refVal: number, minSize: number = 1, maxSize: number = 20, maxDev: number = 3, sort: boolean = true
): number[] {
let list: number[] = [];
const size = minSize + Math.floor(Math.random() * ((maxSize - minSize) + 1)); // between minSize and maxSize
for (let i = 0; i < size; i++) {
let dev = (Math.random() * (2 * maxDev)) - (maxDev + 1); // between -maxDev and maxDev
dev = Number(Math.round(Number(dev + "e3")) + "e-3"); // trick to properly round to 3 decimals
list.push(refVal + dev);
}
if (sort) {
list = list.sort((a, b) => a - b);
}
return list;
}
describe("multiple variated parameters - ", () => {
describe("on the same Nub, with REPEAT_LAST strategy - ", () => {
it("test 1 : minmax < list", () => {
createSingleNubEnv();
prms1.Z1.setValues(100, 102, 0.5); // 5 values
prms1.Z1.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
prmsStruct.L.setValues([ 1.89, 1.91, 1.99, 2, 1.7, 2.1, 2.18, 2.23, 2.6 ]); // 9 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.MINMAX);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.LISTE);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(9);
});
it("test 2 : minmax < minmax", () => {
createSingleNubEnv();
prms1.Z1.setValues(100, 102, 0.5); // 5 values
prms1.Z1.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
prmsStruct.L.setValues(1.89, 2.1, 0.03); // 8 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.MINMAX);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.MINMAX);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(8);
});
it("test 3 : list < minmax", () => {
createSingleNubEnv();
prms1.Z1.setValues(100, 102, 0.1); // 21 values
prms1.Z1.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
prmsStruct.L.setValues([ 1.89, 1.91, 1.99, 2, 1.7, 2.1, 2.18, 2.23, 2.6 ]); // 9 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.MINMAX);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.LISTE);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(21);
});
it("test 4 : list < list", () => {
createSingleNubEnv();
prms1.Z1.setValues([ 100, 101, 102 ]); // 3 values
prms1.Z1.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
prmsStruct.L.setValues([ 1.89, 1.91, 1.99, 2, 1.7, 2.1, 2.18, 2.23, 2.6 ]); // 9 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.LISTE);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.LISTE);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(9);
});
it("test 5 : list = list", () => {
createSingleNubEnv();
prms1.Z1.setValues([ 100, 100.3, 100.7, 101, 101.3, 101.7, 102, 102.3, 115 ]); // 9 values
prms1.Z1.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
prmsStruct.L.setValues([ 1.89, 1.91, 1.99, 2, 1.7, 2.1, 2.18, 2.23, 2.6 ]); // 9 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.LISTE);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.LISTE);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(9);
});
it("test 6 : list = minmax", () => {
createSingleNubEnv();
prms1.Z1.setValues(100, 102, 0.5); // 5 values
prms1.Z1.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
prmsStruct.L.setValues(1.89, 2.15, 0.06); // 5 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.MINMAX);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.MINMAX);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(5);
});
it("test 7 : all parameters varying with random lengths", () => {
createSingleNubEnv();
let longest = 0;
let sparedParam = null;
// set all parameters to LIST mode with random length (except the first that has to stay in CALC mode)
for (const p of nub1.parameterIterator) {
if (p.visible) {
if (! sparedParam) {
sparedParam = p;
} else {
const rl = randomList(p.singleValue);
longest = Math.max(longest, rl.length);
p.setValues(rl);
p.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
}
}
}
// check that all parameters are varying
for (const p of nub1.parameterIterator) {
if (p.visible && p !== sparedParam) {
expect(p.hasMultipleValues).toBe(true);
}
}
// check that calculation works and length of result is length of the longest values list
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(longest);
});
});
describe("on the same Nub, with RECYCLE strategy - ", () => {
it("test 1 : minmax < list", () => {
createSingleNubEnv();
prms1.Z1.setValues(100, 102, 0.5); // 5 values
prms1.Z1.extensionStrategy = ExtensionStrategy.RECYCLE;
prmsStruct.L.setValues([ 1.89, 1.91, 1.99, 2, 1.7, 2.1, 2.18, 2.23, 2.6]); // 9 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.RECYCLE;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.MINMAX);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.LISTE);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(9);
});
it("test 2 : minmax < minmax", () => {
createSingleNubEnv();
prms1.Z1.setValues(100, 102, 0.5); // 5 values
prms1.Z1.extensionStrategy = ExtensionStrategy.RECYCLE;
prmsStruct.L.setValues(1.89, 2.1, 0.03); // 8 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.RECYCLE;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.MINMAX);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.MINMAX);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(8);
});
it("test 3 : list < minmax", () => {
createSingleNubEnv();
prms1.Z1.setValues(100, 102, 0.1); // 21 values
prms1.Z1.extensionStrategy = ExtensionStrategy.RECYCLE;
prmsStruct.L.setValues([ 1.89, 1.91, 1.99, 2, 1.7, 2.1, 2.18, 2.23, 2.6 ]); // 9 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.RECYCLE;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.MINMAX);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.LISTE);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(21);
});
it("test 4 : list < list", () => {
createSingleNubEnv();
prms1.Z1.setValues([ 100, 101, 102 ]); // 3 values
prms1.Z1.extensionStrategy = ExtensionStrategy.RECYCLE;
prmsStruct.L.setValues([ 1.89, 1.91, 1.99, 2, 1.7, 2.1, 2.18, 2.23, 2.6 ]); // 9 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.RECYCLE;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.LISTE);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.LISTE);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(9);
});
it("test 5 : list = list", () => {
createSingleNubEnv();
prms1.Z1.setValues([ 100, 100.3, 100.7, 101, 101.3, 101.7, 102, 102.3, 115 ]); // 9 values
prms1.Z1.extensionStrategy = ExtensionStrategy.RECYCLE;
prmsStruct.L.setValues([ 1.89, 1.91, 1.99, 2, 1.7, 2.1, 2.18, 2.23, 2.6 ]); // 9 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.RECYCLE;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.LISTE);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.LISTE);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(9);
});
it("test 6 : list = minmax", () => {
createSingleNubEnv();
prms1.Z1.setValues(100, 102, 0.5); // 5 values
prms1.Z1.extensionStrategy = ExtensionStrategy.RECYCLE;
prmsStruct.L.setValues(1.89, 2.15, 0.06); // 5 values
prmsStruct.L.extensionStrategy = ExtensionStrategy.RECYCLE;
// check that both parameters are varying
expect(prms1.Z1.valueMode).toBe(ParamValueMode.MINMAX);
expect(prmsStruct.L.valueMode).toBe(ParamValueMode.MINMAX);
// check that calculation works
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(5);
});
it("test 7 : all parameters varying with random lengths", () => {
createSingleNubEnv();
let longest = 0;
let sparedParam = null;
// set all parameters to LIST mode with random length (except the first that has to stay in CALC mode)
for (const p of nub1.parameterIterator) {
if (p.visible) {
if (! sparedParam) {
sparedParam = p;
} else {
const rl = randomList(p.singleValue);
longest = Math.max(longest, rl.length);
p.setValues(rl);
p.extensionStrategy = ExtensionStrategy.RECYCLE;
}
}
}
// check that all parameters are varying
for (const p of nub1.parameterIterator) {
if (p.visible && p !== sparedParam) {
expect(p.hasMultipleValues).toBe(true);
}
}
// check that calculation works and length of result is length of the longest values list
const res = nub1.CalcSerie();
expect(res).toBeDefined();
expect(res.resultElements.length).toBe(longest);
});
});
describe("on different linked Nubs - ", () => {
// TODO
});
});
......@@ -3,7 +3,7 @@ import { Dichotomie } from "./dichotomie";
import { acSection, IParamDefinitionIterator, Pab, ParamDefinition, ParamsEquation,
ParamsEquationArrayIterator, Session, Structure } from "./index";
import { LinkedValue } from "./linked-value";
import { ParamCalculability } from "./param/param-definition";
import { ExtensionStrategy, ParamCalculability } from "./param/param-definition";
import { ParamValueMode } from "./param/param-value-mode";
import { ParamValues } from "./param/param-values";
import { Props } from "./props";
......@@ -146,8 +146,22 @@ export abstract class Nub extends ComputeNode implements IObservable {
}
/**
* Resets the calculated parameter to the default one if it is in SINGLE
* mode, or else to the first calculable parameter other than requirer.
* Finds the previous calculated parameter and sets its mode to SINGLE
*/
public unsetCalculatedParam(except: ParamDefinition) {
for (const p of this.parameterIterator) {
if (p !== except) {
p.setValueMode(ParamValueMode.SINGLE, false);
}
}
}
/**
* Tries to reset the calculated parameter, successively, to :
* - the default one if it is in SINGLE mode
* - the first SINGLE calculable parameter other than requirer
* - the first MINMAX/LISTE calculable parameter other than requirer
*
* If no default calculated parameter is defined, does nothing.
*/
public resetDefaultCalculatedParam(requirer?: ParamDefinition) {
......@@ -155,15 +169,24 @@ export abstract class Nub extends ComputeNode implements IObservable {
// if default calculated param is not eligible to CALC mode
if (
requirer === this._defaultCalculatedParam
|| this._defaultCalculatedParam.valueMode !== ParamValueMode.SINGLE
|| ! [
ParamValueMode.SINGLE,
ParamValueMode.MINMAX,
ParamValueMode.LISTE
].includes(this._defaultCalculatedParam.valueMode
)
) {
// first SINGLE calculable parameter if any
const newCalculatedParam = this.findFirstSingleParameter(requirer);
let newCalculatedParam = this.findFirstSingleParameter(requirer);
if (! newCalculatedParam) {
// first MIMAX/LISTE calculable parameter if any
newCalculatedParam = this.findFirstVariableParameter(requirer);
}
if (newCalculatedParam) {
this.calculatedParam = newCalculatedParam;
} else {
// @TODO throws when a new linkable nub is added, and all parameters are already linked !
throw Error("resetDefaultCalculatedParam : could not find any SINGLE parameter");
throw Error("resetDefaultCalculatedParam : could not find any SINGLE/MINMAX/LISTE parameter");
}
} else {
// default one
......@@ -195,42 +218,23 @@ export abstract class Nub extends ComputeNode implements IObservable {
}
/**
* Resets all parameters to SINGLE mode, except sourceParam (the one that asked
* for the change) and parameters in LINK mode.
* If exceptMode is defined, parameters in this mode won't be affected either.
*
* Used to ensure that
* - exactly one parameter is in CALCUL mode
* - at most one parameter variates (MIMAX / LISTE mode)
* Returns the first visible calculable parameter other than "Pr",
* and other than otherThan, that is set to MINMAX or LISTE mode
* (there might be none)
*/
public ensureParametersConsistency(sourceParam: ParamDefinition, exceptMode: ParamValueMode|ParamValueMode[] = []) {
if (! Array.isArray(exceptMode)) {
exceptMode = [ exceptMode ];
}
// console.log(`nub ${this.uid} (${this.constructor.name})`);
// console.log(`(calculated parameter: ${this.calculatedParam.symbol})`);
public findFirstVariableParameter(otherThan?: ParamDefinition) {
for (const p of this.parameterIterator) {
if (
p !== sourceParam
&& ! exceptMode.includes(p.valueMode)
&& (
// don't touch linked parameters
p.valueMode !== ParamValueMode.LINK
|| ( // unless they are linked to multiple values…
p.isReferenceDefined()
&& p.hasMultipleValues
// …and we're not skipping multiple values
&& ! exceptMode.includes(ParamValueMode.MINMAX)
&& ! exceptMode.includes(ParamValueMode.LISTE)
)
)
&& p.valueMode !== ParamValueMode.SINGLE
[ ParamCalculability.EQUATION, ParamCalculability.DICHO ].includes(p.calculability)
&& p.symbol !== "Pr"
&& p.visible
&& p !== otherThan
&& [ ParamValueMode.SINGLE, ParamValueMode.MINMAX, ParamValueMode.LISTE ].includes(p.valueMode)
) {
// console.log(">> resetting", p.symbol);
// "false" prevents infinite loop when managing CALC params
p.setValueMode(ParamValueMode.SINGLE, false);
return p;
}
}
return undefined;
}
/**
......@@ -304,42 +308,37 @@ export abstract class Nub extends ComputeNode implements IObservable {
* @param sDonnee éventuel symbole / paire symbole-uid du paramètre à calculer
*/
public CalcSerie(rInit?: number, sDonnee?: any): Result {
// instance de ParamValues utilisée pour le paramètre varié (qui peut être un paramètre référencé (importé))
let variatedParam: ParamDefinition;
let variatedValues: ParamValues;
// variated parameters caracteristics
const variated: Array<{ param: ParamDefinition, values: ParamValues, extendedValues: number[] }> = [];
// prepare calculation
this.progress = 0;
this.triggerChainCalculation();
this.copySingleValuesToSandboxValues();
// check which values are variating, if any
for (const p of this.parameterIterator) {
switch (p.valueMode) {
case ParamValueMode.SINGLE:
case ParamValueMode.CALCUL:
break;
case ParamValueMode.LISTE:
case ParamValueMode.MINMAX:
variatedParam = this.setVariatedValues(p, variatedParam);
break;
case ParamValueMode.LINK:
if (
p.isReferenceDefined()
&& p.referencedValue.hasMultipleValues()
) {
variatedParam = this.setVariatedValues(p, variatedParam);
}
break;
default:
// tslint:disable-next-line:max-line-length
throw new Error(`CalcSerie() : valeur de ParamValueMode ${ParamValueMode[p.valueMode]} non prise en charge`);
if (
p.valueMode === ParamValueMode.LISTE
|| p.valueMode === ParamValueMode.MINMAX
|| (
p.valueMode === ParamValueMode.LINK
&& p.isReferenceDefined()
&& p.referencedValue.hasMultipleValues()
)
) {
variated.push({
param: p,
// extract variated values from variated Parameters
// (in LINK mode, proxies to target data)
values: p.paramValues,
// values list by default, will be extended later
extendedValues: p.paramValues.getInferredValuesList()
});
}
}
// find calculated parameter
let computedSymbol: any;
if (sDonnee) {
computedSymbol = sDonnee;
......@@ -354,31 +353,74 @@ export abstract class Nub extends ComputeNode implements IObservable {
rInit = this.calculatedParam.v;
}
if (variatedParam === undefined) {
this._result = this.Calc(computedSymbol, rInit); // résultat dans this._result
// update progress to 100%
if (variated.length === 0) { // no parameter is varying
this._result = this.doCalc(computedSymbol, rInit);
this.progress = 100;
} else {
// extract variated values from variated Parameter
// (in LINK mode, proxies to target data)
variatedValues = variatedParam.paramValues;
} else { // at least one parameter is varying
// find longest series
let longest = 0;
for (let i = 0; i < variated.length; i++) {
if (variated[i].values.valuesIterator.count() > variated[longest].values.valuesIterator.count()) {
longest = i;
}
}
// for all variating parameters other than the longest one,
// complete the series depending on the strategy (recycle / extend)
const size = variated[longest].values.valuesIterator.count();
for (let i = 0; i < variated.length; i++) {
if (i !== longest) {
const vp = variated[i].param;
const vxv = variated[i].extendedValues;
// if sizes differ
if (vxv.length < size) {
const newValues = [...vxv]; // array copy
// extend values
switch (vp.extensionStrategy) {
case ExtensionStrategy.REPEAT_LAST:
while (newValues.length < size) {
newValues.push(vxv[vxv.length - 1]);
}
break;
case ExtensionStrategy.RECYCLE:
let j = 0;
while (newValues.length < size) {
newValues.push(vxv[j]);
j ++;
if (j === vxv.length) {
j = 0;
}
}
break;
}
// store extended values
variated[i].extendedValues = newValues;
}
}
}
// grant the remaining percentage of the progressbar to local calculation
// (should be 50% if any chain calculation occurred, 100% otherwise)
let progressStep;
const remainingProgress = 100 - this.progress;
const nbValues = variatedValues.valuesIterator.count();
const nbValues = variated[longest].extendedValues.length;
progressStep = remainingProgress / nbValues;
const res = new Result(undefined, this);
variatedValues.initValuesIterator(false);
while (variatedValues.hasNext) {
const currentIteratorValue = variatedValues.next();
variatedParam.v = currentIteratorValue.value; // copy to local sandbox value
// iterate over longest series @TODO iterate over extendedValues directly ?
variated[longest].values.initValuesIterator(false);
let index = 0;
while (variated[longest].values.hasNext) {
variated[longest].values.next(); // move on
// get next value for all variating parameters
for (const v of variated) {
v.param.v = v.extendedValues[index]; // copy to local sandbox value
}
this.Calc(computedSymbol, rInit); // résultat dans this._result
this.doCalc(computedSymbol, rInit); // résultat dans this._result
if (this._result.ok) {
res.addResultElement(this._result.resultElement);
res.addLog(this._result.log);
......@@ -387,6 +429,7 @@ export abstract class Nub extends ComputeNode implements IObservable {
res.globalLog.addLog(this._result.globalLog);
// update progress
this.progress += progressStep;
index ++;
}
this._result = res;
// round progress to 100%
......@@ -1098,6 +1141,10 @@ export abstract class Nub extends ComputeNode implements IObservable {
this._observable.notifyObservers(data, sender);
}
protected doCalc(computedSymbol?: any, rInit?: number) {
return this.Calc(computedSymbol, rInit);
}
/**
* Returns values of parameters and the result of the calculation for the calculated parameter
* @param sVarCalc Symbol of the calculated param
......@@ -1147,18 +1194,6 @@ export abstract class Nub extends ComputeNode implements IObservable {
return Nub.prototype.Calc.call(this, sVarCalc, rInit);
}
/**
* Sets the variated values and warns if there were already some
*/
protected setVariatedValues(newValues: ParamDefinition, oldValues: ParamDefinition): ParamDefinition {
if (oldValues === undefined) {
return newValues;
} else {
// tslint:disable-next-line:max-line-length
throw new Error(`CalcSerie() : Paramètres à varier redondant : ${newValues.name}`);
}
}
/**
* Used by GUI to update results display
*/
......
......@@ -43,6 +43,19 @@ export enum ParamFamily {
// SPEEDS // vitesses, seulement des résultats
}
/**
* Strategy to apply when multiple parameters are variating, and
* values series have to be extended for sizes to match
*/
export enum ExtensionStrategy {
REPEAT_LAST, // repeat last value as many times as needed
RECYCLE // repeat the whole series from the beginning
// autres propositions :
// PAD_LEFT // pad with zeroes at the beginning ?
// PAD_RIGHT // pad with zeroes at the end ?
// INTERPOLATE // insert regular steps between first and last value
}
/**
* Paramètre avec symbole, famille, domaine de définition, calculabilité,
* pointant éventuellement vers un autre paramètre / résultat
......@@ -55,6 +68,9 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
/** sandbox value used during calculation */
public v: number;
/** extension strategy, when multiple parameters vary */
public extensionStrategy: ExtensionStrategy;
/** mode de génération des valeurs : min/max, liste, ... */
private _valueMode: ParamValueMode;
......@@ -90,7 +106,7 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
this._observable = new Observable();
this._paramValues = new ParamValues();
// set single value and copy it to currentValue
// set single value and copy it to sandbox value
this._paramValues.singleValue = val;
this.v = val;
......@@ -98,6 +114,7 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
this._family = family;
this.visible = visible;
this.valueMode = ParamValueMode.SINGLE;
this.extensionStrategy = ExtensionStrategy.REPEAT_LAST;
if (d instanceof ParamDomain) {
this._domain = d;
......@@ -203,8 +220,8 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
}
/**
* Sets the value mode and asks the Nub to ensure all parameters requirements are met
* @see Nub::ensureParametersConsistency()
* Sets the value mode and asks the Nub to ensure there is only one parameter
* in CALC mode
*
* If propagateToCalculatedParam is true, any param that goes from CALC mode
* to any other mode will trigger a reset of the default calculated param at
......@@ -221,88 +238,19 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
return;
}
switch (oldMode) {
case ParamValueMode.SINGLE: // ancien état
switch (newMode) {
case ParamValueMode.MINMAX: // nouvel état
case ParamValueMode.LISTE:
this.ensureParametersConsistency(this, ParamValueMode.CALCUL);
break;
case ParamValueMode.CALCUL: // nouvel état
this.ensureParametersConsistency(this, [ ParamValueMode.MINMAX, ParamValueMode.LISTE ]);
break;
case ParamValueMode.LINK: // nouvel état
if (
this.isReferenceDefined()
&& this.hasMultipleValues
) {
this.ensureParametersConsistency(this); // reset existing variable param
}
break;
}
break;
case ParamValueMode.LISTE: // ancien état
case ParamValueMode.MINMAX:
switch (newMode) {
case ParamValueMode.CALCUL: // nouvel état
this.ensureParametersConsistency(this);
break;
case ParamValueMode.LINK: // nouvel état
if (
this.isReferenceDefined()
&& this.hasMultipleValues
) {
this.ensureParametersConsistency(this); // reset existing variable param
}
break;
}
break;
case ParamValueMode.LINK: // ancien état
switch (newMode) {
case ParamValueMode.MINMAX: // nouvel état
case ParamValueMode.LISTE:
this.ensureParametersConsistency(this, ParamValueMode.CALCUL);
break;
case ParamValueMode.CALCUL: // nouvel état
this.ensureParametersConsistency(this, [ ParamValueMode.MINMAX, ParamValueMode.LISTE ]);
break;
}
break;
case ParamValueMode.CALCUL: // ancien état
switch (newMode) {
case ParamValueMode.SINGLE: // nouvel état
break;
case ParamValueMode.MINMAX: // nouvel état
case ParamValueMode.LISTE:
this.ensureParametersConsistency(this);
break;
case ParamValueMode.LINK: // nouvel état
if (
this.isReferenceDefined()
&& this.hasMultipleValues
) {
this.ensureParametersConsistency(this); // reset existing variable param
}
break;
if (oldMode === ParamValueMode.CALCUL) {
if (propagateToCalculatedParam) {
// Set default calculated parameter, only if previous CALC param was
// manually set to something else than CALC
if (this.parentComputeNode && this.parentComputeNode instanceof Nub) {
this.parentComputeNode.resetDefaultCalculatedParam(this);
}
if (propagateToCalculatedParam) {
// Set default calculated parameter, only if previous CALC param was
// manually set to something else than CALC
if (this.parentComputeNode && this.parentComputeNode instanceof Nub) {
this.parentComputeNode.resetDefaultCalculatedParam(this);
}
}
}
} else if (newMode === ParamValueMode.CALCUL) {
// set old CALC param to SINGLE mode
if (this.parentComputeNode && this.parentComputeNode instanceof Nub) {
this.parentComputeNode.unsetCalculatedParam(this);
}
}
// set new mode
......@@ -500,6 +448,15 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
return this.paramValues.singleValue;
}
/**
* Returns values as a number list, for LISTE and MINMAX modes;
* in MINMAX mode, infers the list from min/max/step values
*/
public getInferredValuesList() {
this.checkValueMode([ParamValueMode.LISTE, ParamValueMode.MINMAX, ParamValueMode.LINK]);
return this.paramValues.getInferredValuesList();
}
/**
* Magic method to define current values into Paramvalues set; defines the mode
* accordingly by detecting values nature
......@@ -1076,17 +1033,6 @@ export class ParamDefinition implements INamedIterableValues, IObservable {
return res;
}
/**
* Asks parent Nub if any to ensure parameters consistency
*/
protected ensureParametersConsistency(sourceParam: ParamDefinition,
exceptMode: ParamValueMode|ParamValueMode[] = []
) {
if (this.parentComputeNode && this.parentComputeNode instanceof Nub) {
this.parentComputeNode.ensureParametersConsistency(sourceParam, exceptMode);
}
}
/**
* notification envoyée après la modification de la valeur du paramètre
*/
......
......@@ -104,6 +104,26 @@ export class ParamValues implements IterableValues {
}
}
/**
* Returns values as a number list, for LISTE and MINMAX modes;
* in MINMAX mode, infers the list from min/max/step values
*/
public getInferredValuesList() {
if (this.valueMode === ParamValueMode.LISTE) {
return this.valueList;
}
if (this.valueMode === ParamValueMode.MINMAX) {
const values = [ this.min ];
let latestVal = this.min + this.step;
while (latestVal <= this.max) {
values.push(latestVal);
latestVal += this.step;
}
return values;
}
throw new Error("ParamValues.getInferredValuesList() : incorrect value mode" + ParamValueMode[this.valueMode]);
}
// -- iterator-related methods
/**
......
......@@ -69,67 +69,6 @@ export class SectionParametree extends SectionNub {
}
}
public CalcSerie(rInit?: number, sDonnee?: string): Result {
this.triggerChainCalculation();
let variatedParam: ParamDefinition;
let variatedValues: ParamValues;
for (const p of this.parameterIterator) {
// checks which values are variating, if any
switch (p.valueMode) {
case ParamValueMode.SINGLE:
case ParamValueMode.CALCUL:
break;
case ParamValueMode.LISTE:
case ParamValueMode.MINMAX:
variatedParam = this.setVariatedValues(p, variatedParam);
break;
case ParamValueMode.LINK:
if (
p.isReferenceDefined()
&& p.referencedValue.hasMultipleValues()
) {
variatedParam = this.setVariatedValues(p, variatedParam);
}
break;
default:
// tslint:disable-next-line:max-line-length
throw new Error(`CalcSerie() : valeur de ParamValueMode ${ParamValueMode[p.valueMode]} non prise en charge`);
}
}
if (variatedParam === undefined) {
this.Calc(); // résultat dans this._result
} else {
// extract variated values from variated Parameter
// (in LINK mode, proxies to target data)
variatedValues = variatedParam.paramValues;
const res = new Result(undefined, this);
variatedValues.initValuesIterator(false);
while (variatedValues.hasNext) {
variatedValues.next();
this.Calc(); // résultat dans this._result
if (this._result.ok) {
res.addResultElement(this._result.resultElement);
res.addLog(this._result.log);
}
res.globalLog.addLog(this._result.globalLog);
}
this._result = res;
}
this.notifyResultUpdated();
return this._result;
}
/**
* Aucune variable à calculer plus que les autres, on stocke toutes les
* valeurs des variables à calcul dans les résultats complémentaires
......@@ -198,6 +137,10 @@ export class SectionParametree extends SectionNub {
return this._result;
}
protected doCalc(computedSymbol?: any, rInit?: number) {
return this.Calc();
}
// tslint:disable-next-line:no-empty
protected setParametersCalculability(): void {}
......
......@@ -106,9 +106,9 @@ export abstract class Structure extends Nub {
* Forwards to parent, that has vsibility over
* all the parameters, including the Structure ones
*/
public ensureParametersConsistency(sourceParam: ParamDefinition, exceptMode: ParamValueMode|ParamValueMode[] = []) {
public unsetCalculatedParam(except: ParamDefinition) {
if (this.parent) {
this.parent.ensureParametersConsistency(sourceParam, exceptMode);
this.parent.unsetCalculatedParam(except);
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment