Newer
Older
import { CalculatedParamResults } from "./param-calc-results";
import { ServiceFactory } from "../services/service-factory";
import { ChartType } from "./chart-type";
import { longestVarParam } from "../util/util";
import { FormulaireDefinition } from "../formulaire/definition/form-definition";
import { ResultElement, ParamFamily, capitalize, Nub, VariatedDetails, ParamDefinition, ParamDomain, ParamDomainValue } from "jalhyd";
export class VarResults extends CalculatedParamResults implements PlottableData {
private _variatedParams: VariatedDetails[] = [];
* titre des colonnes des résultats variés
private _variableParamHeaders: string[];
mathias.chouet
committed
* clés des résultats
mathias.chouet
committed
public resultKeys: string[];
mathias.chouet
committed
* entête des colonnes des résultats
mathias.chouet
committed
private _resultHeaders: string[];
protected _graphType: ChartType = ChartType.Scatter;
/** pointer to form that instantiated this object */
protected _form: FormulaireDefinition;
mathias.chouet
committed
* variated parameter or result displayed as chart's X-axis
mathias.chouet
committed
public chartX: string;
/**
* variated parameter or result displayed as chart's Y-axis
*/
public chartY: string;
/** size of the longest variated parameter */
public size: number;
mathias.chouet
committed
/** index of the longest variated parameter */
public longest: number;
* tableau des ordonnées du graphique des résultats variés
*/
private _yValues: number[] = [];
constructor(form?: FormulaireDefinition) {
this.reset();
}
public reset() {
super.reset();
this._variableParamHeaders = [];
mathias.chouet
committed
this._resultHeaders = [];
this.resultKeys = [];
this._yValues = [];
mathias.chouet
committed
this.longest = 0;
public get variatedParameters(): VariatedDetails[] {
return this._variatedParams;
public set variatedParameters(p: VariatedDetails[]) {
public get variableParamHeaders() {
return this._variableParamHeaders;
}
public get yValues() {
return this._yValues;
}
public get resultElements(): ResultElement[] {
mathias.chouet
committed
public get resultHeaders() {
return this._resultHeaders;
this._graphType = gt;
this.resetDefaultAxisIfNeeded();
}
public hasPlottableResults(): boolean {
if (this.result === undefined) {
return false;
return ! this.result.hasOnlyErrors;
}
public getChartAxisLabel(symbol: string): string {
if (this.result) {
// 1. calculated param ?
if (this.calculatedParameter && this.calculatedParameter.symbol === symbol) {
return this.calculatedParameterHeader;
}
// 2. variated param ?
for (let i = 0; i < this.variatedParameters.length; i++) {
if (this._variatedParams[i].param.symbol === symbol) {
return this.variableParamHeaders[i];
}
// 3. Result element / child result
return this.expandLabelFromSymbol(new ParamDefinition(undefined, symbol, ParamDomainValue.ANY));
* Returns the translated name of the given symbol (usually a result or child result) with
* its unit, but without the symbol itself
*/
public expandLabelFromSymbol(p: ParamDefinition): string {
mathias.chouet
committed
let ret = "";
// calculator type for translation
const sn = this.result.sourceNub;
let ct = sn.calcType;
if (sn.parent) {
ct = sn.parent.calcType;
}
mathias.chouet
committed
// detect children results
const match = /^([0-9]+)_(.+)$/.exec(p.symbol);
let symbol = p.symbol;
mathias.chouet
committed
if (match !== null) {
const pos = +match[1];
mathias.chouet
committed
// only parent translation file is loaded; look for children translations in it // ct = sn.getChildren()[pos].calcType;
mathias.chouet
committed
symbol = match[2];
const cn = capitalize(ServiceFactory.i18nService.childName(sn.getChildren()[0]));
ret += sprintf(ServiceFactory.i18nService.localizeText("INFO_STUFF_N"), cn) + (pos + 1) + " : ";
mathias.chouet
committed
}
ret += ServiceFactory.formulaireService.expandVariableNameAndUnit(ct, symbol);
mathias.chouet
committed
return ret;
mathias.chouet
committed
/**
* Returns the series of values for the required variated parameter / result element
mathias.chouet
committed
* @param symbol parameter / result symbol (ex: "Q", "0_Q"...)
mathias.chouet
committed
*/
public getValuesSeries(symbol: string): number[] {
let found = false;
const series: number[] = [];
// detect children results
const isChildResult = /^([0-9]+)_(.+)$/.exec(symbol);
mathias.chouet
committed
// 1. variated param ?
for (let i = 0; i < this.variatedParameters.length; i++) {
const vp = this._variatedParams[i];
let isTheGoodChild = false;
// are we looking for a child variated param ?
if (isChildResult !== null) {
const children = this.result.sourceNub.getChildren();
const parameterNub = vp.param.parentNub;
if (children.includes(parameterNub)) { // current var param is a child param !
const pos = parameterNub.findPositionInParent();
isTheGoodChild = (pos === +isChildResult[1] && vp.param.symbol === isChildResult[2]);
if (isTheGoodChild || vp.param.symbol === symbol) {
const iter = vp.param.getExtendedValuesIterator(this.size);
for (const v of iter) {
mathias.chouet
committed
}
mathias.chouet
committed
// 2. Result element ?
if (! found) {
for (const r of this.result.resultElements) { // re:ResultElement
for (const k in r.values) {
if (k === symbol) {
found = true;
series.push(r.getValue(k));
}
mathias.chouet
committed
}
}
}
mathias.chouet
committed
// 3. Child result element ?
const child = sn.getChildren()[pos];
for (const r of child.result.resultElements) {
series.push(r.getValue(symbol));
}
mathias.chouet
committed
}
}
mathias.chouet
committed
return series;
}
/**
* Returns a list of plottable parameters / result elements, that can be defined
mathias.chouet
committed
*/
let res: string[] = [];
res = res.concat(this.getVariatingParametersSymbols());
mathias.chouet
committed
for (const erk of this.resultKeys) {
if (erk.indexOf("ENUM_") === -1) { // ENUM variables are not plottable
res.push(erk);
}
}
// children results
if (this.result) {
const sn = this.result.sourceNub;
for (const c of sn.getChildren()) {
if (c.result) {
// using latest ResultElement; results count / types are supposed to be the same on every iteration
for (const k of c.result.resultElement.keys) {
if (k.indexOf("ENUM_") === -1) { // ENUM variables are not plottable
res.push(c.findPositionInParent() + "_" + k);
}
mathias.chouet
committed
}
}
mathias.chouet
committed
}
return res;
}
* Same as X axis, plus results families if chart type is Scatter
* (for multi-series comparison)
*/
public getAvailableYAxis(): string[] {
const res: string[] = this.getAvailableXAxis();
if (this._graphType === ChartType.Scatter) {
// add families having more than 1 variable as plottable ordinates
const families = this.extractFamilies();
for (const f in families) {
if (families[f].length > 1) {
res.push(f);
}
}
}
return res;
}
/**
* Browses all parameters and results to produce a map of families => list of
* symbols in this family
*/
// exclude pseudo-family "ANY"
if (fam !== undefined && fam !== ParamFamily.ANY) {
const f = ParamFamily[fam];
families[f].push(v.param.symbol);
mathias.chouet
committed
for (const erk of this.resultKeys) {
const fam = this.result.sourceNub.getFamily(erk);
// exclude pseudo-family "ANY"
if (fam !== undefined && fam !== ParamFamily.ANY) {
const f = ParamFamily[fam];
if (! (f in families)) {
families[f] = [];
}
families[f].push(erk);
}
}
if (this.result) {
const sn = this.result.sourceNub;
for (const c of sn.getChildren()) {
if (c.result) {
for (const k of c.result.resultElement.keys) {
const fam = this.result.sourceNub.getFamily(k);
// exclude pseudo-family "ANY"
if (fam !== undefined && fam !== ParamFamily.ANY) {
const f = ParamFamily[fam];
if (! (f in families)) {
families[f] = [];
}
const pos = c.findPositionInParent();
families[f].push(pos + "_" + k);
/**
* Returns the list of variating parameters
* (used by tooltip functions)
*/
public getVariatingParametersSymbols(): string[] {
if (this.result && this.result.sourceNub) {
return this._variatedParams.map(vp => this.getVariatingParameterSymbol(vp.param, this.result.sourceNub));
public getVariatingParameterSymbol(vp: ParamDefinition, sourceNub: Nub): string {
// detect if variated param is a children param
const parameterNub = vp.parentNub;
const children = sourceNub.getChildren();
let symb = vp.symbol;
if (children.includes(parameterNub)) {
symb = parameterNub.findPositionInParent() + "_" + symb;
}
return symb;
}
// refresh param headers and build source nub headers
const parentVariatedParameters = this._variatedParams.filter(v => v.param.nubCalcType === this.result.sourceNub.calcType);
this._variableParamHeaders = parentVariatedParameters.map((v) => {
let h = this.expandLabelFromSymbol(v.param);
h += this.getHelpLink(v.param.symbol);
// liste la plus longue
const lvp = longestVarParam(this._variatedParams);
this.size = lvp.size;
this.longest = lvp.index;
mathias.chouet
committed
// result keys (extra or not) - some lines might miss some results, in case of an error;
// use those keys to ensure all columns are filled
if (this.resultKeys.length === 0) {
if (this.result.symbol !== undefined) {
this.resultKeys.push(this.result.symbol);
}
for (const re of this.result.resultElements) { // re:ResultElement
mathias.chouet
committed
for (const erk in re.values) {
if (!this.resultKeys.includes(erk)) {
this.resultKeys.push(erk);
// set axis selectors values the first time
let defaultY = this.chartY;
mathias.chouet
committed
if (this.resultKeys.length > 0) {
defaultY = this.resultKeys[0];
}
this.chartY = defaultY;
if (this.chartX === undefined || ! this.getAvailableXAxis().includes(this.chartX)) {
this.chartX = this.getVariatingParameterSymbol(this.variatedParameters[this.longest].param, this.result.sourceNub);
// calculator type for translation
const sn = this.result.sourceNub;
let ct = sn.calcType;
if (sn.parent) {
ct = sn.parent.calcType;
console.log("ct", ct);
mathias.chouet
committed
// entêtes des résultats
this._resultHeaders = [];
for (const k of this.resultKeys) {
let unit;
// is k the calculated parameter ? If so, extract its unit
try {
const p = sn.getParameter(k);
if (p) {
unit = p.unit;
}
} catch (e) { /* silent fail */ }
let rh = ServiceFactory.formulaireService.expandVariableNameAndUnit(ct, k, unit);
rh += this.getHelpLink(k);
this._resultHeaders.push(rh);
mathias.chouet
committed
// entêtes des résultats des enfants
for (const c of sn.getChildren()) {
const cn = capitalize(ServiceFactory.i18nService.childName(c));
// using latest ResultElement; results count / types are supposed to be the same on every iteration
for (const k of c.result.resultElement.keys) {
let rh = sprintf(ServiceFactory.i18nService.localizeText("INFO_STUFF_N"), cn)
+ (c.findPositionInParent() + 1) + " : "
+ ServiceFactory.formulaireService.expandVariableNameAndUnit(ct, k);
rh += this.getHelpLink(k);
this._resultHeaders.push(rh);
// build header for children variated parameters
for (const v of c.findVariatedParams()) {
let h = sprintf(ServiceFactory.i18nService.localizeText("INFO_STUFF_N"), cn)
+ (c.findPositionInParent() + 1) + " : "
+ ServiceFactory.formulaireService.expandVariableNameAndUnit(ct, v.param.symbol);
h += this.getHelpLink(v.param.symbol);
this.variableParamHeaders.push(h);
}
// this.variableParamHeaders.push()
mathias.chouet
committed
}
}
mathias.chouet
committed
* When variable parameter or chart type changes, ensure the X / Y current values are still available
if (this.variatedParameters.length > 0 && ! this.getAvailableXAxis().includes(this.chartX)) {
this.chartX = this.variatedParameters[0].param.symbol;
mathias.chouet
committed
}
if (this.variatedParameters.length > 0 && ! this.getAvailableYAxis().includes(this.chartY)) {
this.chartY = this.variatedParameters[0].param.symbol;
mathias.chouet
committed
}