Commit ec5a720d authored by Mathias Chouet's avatar Mathias Chouet 🍝
Browse files

Merge branch '187-section-parametree-varier-un-parametre-fait-echouer-le-calcul' into 'master'

Resolve "Section paramétrée: varier un paramètre fait échouer le calcul"

Closes #187, #175, and #161

See merge request !43
parents a2008550 344261fd
26-ajout-de-la-calculette-passe-a-bassins-calcul-du-nombre-de-bassins
75-section-parametree-calculer-systematiquement-toutes-les-variables-meme-avec-un-parametre-qui-varie
......@@ -150,128 +150,6 @@
}
]
},
{
"id": "fs_computed_var",
"type": "fieldset",
"dep_exist": [
{
"refid": "LargeurFond",
"cond": "isvar"
},
{
"refid": "Fruit",
"cond": "isvar"
},
{
"refid": "D",
"cond": "isvar"
},
{
"refid": "k",
"cond": "isvar"
},
{
"refid": "LargeurBerge",
"cond": "isvar"
},
{
"refid": "Ks",
"cond": "isvar"
},
{
"refid": "If",
"cond": "isvar"
},
{
"refid": "YB",
"cond": "isvar"
},
{
"refid": "Q",
"cond": "isvar"
},
{
"refid": "Y",
"cond": "isvar"
}
],
"fields": [
{
"id": "select_target",
"type": "select",
"select": [
{
"id": "select_target_Hs",
"value": "Hs"
},
{
"id": "select_target_Hsc",
"value": "Hsc"
},
{
"id": "select_target_B",
"value": "B"
},
{
"id": "select_target_P",
"value": "P"
},
{
"id": "select_target_S",
"value": "S"
},
{
"id": "select_target_R",
"value": "R"
},
{
"id": "select_target_V",
"value": "V"
},
{
"id": "select_target_Fr",
"value": "Fr"
},
{
"id": "select_target_Yc",
"value": "Yc"
},
{
"id": "select_target_Yn",
"value": "Yn"
},
{
"id": "select_target_Yf",
"value": "Yf"
},
{
"id": "select_target_Yt",
"value": "Yt"
},
{
"id": "select_target_Yco",
"value": "Yco"
},
{
"id": "select_target_J",
"value": "J"
},
{
"id": "select_target_I-J",
"value": "I-J"
},
{
"id": "select_target_Imp",
"value": "Imp"
},
{
"id": "select_target_Tau0",
"value": "Tau0"
}
]
}
]
},
{
"type": "options",
"defaultNodeType": "SectionRectangle",
......
......@@ -77,7 +77,7 @@
<!-- langue -->
<mat-form-field>
<mat-select placeholder="Language" [(value)]="currentLanguageCode" data-testid="language-select">
<mat-select [placeholder]="uitextLanguage" [(value)]="currentLanguageCode" data-testid="language-select">
<mat-option *ngFor="let l of availableLanguages | keyvalue" [value]="l.key">
{{ l.value }}
</mat-option>
......
......@@ -56,6 +56,10 @@ export class ApplicationSetupComponent extends BaseComponent implements Observer
return this.intlService.localizeText("INFO_SETUP_TITLE");
}
public get uitextLanguage(): string {
return this.intlService.localizeText("INFO_SETUP_LANGUAGE");
}
public get uitextDisplayAccuracy(): string {
return this.intlService.localizeText("INFO_SETUP_PRECISION_AFFICHAGE");
}
......
<div class="container" fxLayout="row wrap" fxLayoutAlign="space-evenly stretch">
<mat-card class="welcome-card" *ngIf="nbOpenCalculators === 0">
<mat-card-header>
<!-- <img mat-card-avatar src="https://s3.amazonaws.com/pix.iemoji.com/images/emoji/apple/ios-12/256/water-wave.png"> -->
<mat-card-title>{{ uitextWelcomeTitle }}</mat-card-title>
<mat-card-subtitle>{{ uitextWelcomeSubtitle }}</mat-card-subtitle>
</mat-card-header>
<mat-card-content [innerHTML]="uitextWelcomeContent">
</mat-card-content>
<img mat-card-image src="../../assets/images/logo_irstea_m.jpg">
<img mat-card-image src="../../assets/images/logo_afb_m.jpg">
<mat-card-actions>
<div class="container" fxLayout="column" fxLayoutAlign="left" fxLayoutGap="10px">
<button mat-raised-button color="accent" class="theme-calculator"></button>
</div>
</mat-card-actions>
</mat-card>
<mat-card *ngFor="let theme of items" class="compute-nodes-theme">
<mat-card-header>
......
mat-card.compute-nodes-theme {
mat-card.compute-nodes-theme, mat-card.welcome-card {
width: 300px;
margin: 1em;
......@@ -47,3 +47,10 @@ mat-card.compute-nodes-theme {
}
}
}
mat-card.welcome-card {
.mat-card-content {
line-height: 1.4em;
}
}
import { Component, OnInit } from "@angular/core";
import { Router } from "@angular/router";
import { CalculatorType, EnumEx } from "jalhyd";
import { CalculatorType, EnumEx, Session } from "jalhyd";
import { FormulaireDefinition } from "../../formulaire/definition/form-definition";
import { ServiceFactory } from "../../services/service-factory";
......@@ -108,10 +108,26 @@ export class CalculatorListComponent implements OnInit {
});
}
public get nbOpenCalculators() {
return Session.getInstance().getNumberOfNubs();
}
public get items() {
return this._items;
}
public get uitextWelcomeTitle() {
return "Cassiopée";
}
public get uitextWelcomeSubtitle() {
return ServiceFactory.instance.i18nService.localizeText("INFO_WELCOME_SUBTITLE");
}
public get uitextWelcomeContent() {
return ServiceFactory.instance.i18nService.localizeText("INFO_WELCOME_CONTENT");
}
// interface Observer
update(sender: any, data: any): void {
......
......@@ -51,7 +51,10 @@ export class VarResultsComponent {
}
this._headers.push(this._varResults.variableParamHeader);
this._headers.push(this._varResults.calculatedParameterHeader);
if (this._varResults.calculatedParameterHeader) {
this._headers.push(this._varResults.calculatedParameterHeader);
}
this._headers = this._headers.concat(this._varResults.extraResultHeaders);
}
}
......@@ -82,7 +85,9 @@ export class VarResultsComponent {
const list = [ r.param ];
// 2. result
list.push(re.vCalc.toFixed(nDigits));
if (re.vCalc) { // sometimes does no exist (ex: Section Parametree)
list.push(re.vCalc.toFixed(nDigits));
}
// 3. extra results
for (const erk of this._varResults.extraResultKeys) {
......
......@@ -7,7 +7,19 @@
</mat-select>
</mat-form-field>
<mat-icon #tooltip="matTooltip" [matTooltip]="tooltipText" matTooltipClass="linked-param-tooltip"
<div class="status-icons-container">
<mat-icon [title]="uitextVariated" class="status-info" *ngIf="isVariable">
show_chart
</mat-icon>
<mat-icon [title]="uitextCalculated" class="status-info" *ngIf="isCalculated && ! isAwaitingCalculation">
check_circle
</mat-icon>
<mat-icon [title]="uitextAwaitingCalculation" class="status-info" *ngIf="isAwaitingCalculation">
timelapse
</mat-icon>
</div>
<mat-icon id="info-tooltip" #tooltip="matTooltip" [matTooltip]="tooltipText" matTooltipClass="linked-param-tooltip"
(click)="tooltip.toggle()"
(mouseenter)="$event.stopImmediatePropagation()" (mouseleave)="$event.stopImmediatePropagation()">
info_outline
......
......@@ -32,11 +32,23 @@
}
}
mat-icon {
.status-icons-container {
position: absolute;
top: 7px;
top: -8px;
right: 8px;
> mat-icon {
transform: scale(0.7);
color: grey;
cursor: default;
}
}
mat-icon#info-tooltip {
position: absolute;
top: 12px;
right: 8px;
transform: scale(0.9);
cursor: pointer;
transform: scale(0.9);
}
}
......@@ -46,6 +46,36 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy {
return "linked_" + this.param.symbol;
}
public get isVariable(): boolean {
return this.param.paramDefinition.hasMultipleValues;
}
/**
* Returns true if current target needs to be calculated,
* whether the result is already available or not
*/
public get isCalculated(): boolean {
const refValue = this.param.paramDefinition.referencedValue;
return (refValue.isResult() || refValue.isExtraResult());
}
/**
* Returns true if current target needs to be calculated,
* but result is not yet available
*/
public get isAwaitingCalculation(): boolean {
if (this.isCalculated) {
const refValue = this.param.paramDefinition.referencedValue;
try {
refValue.getParamValues();
return false;
} catch (e) {
return true;
}
}
return false;
}
constructor(
private intlService: I18nService
) {
......@@ -100,6 +130,18 @@ export class ParamLinkComponent implements OnChanges, Observer, OnDestroy {
return this._currentIndex !== -1 && this.param.isValid;
}
public get uitextVariated() {
return this.intlService.localizeText("INFO_PARAMFIELD_VARIATED");
}
public get uitextCalculated() {
return this.intlService.localizeText("INFO_PARAMFIELD_CALCULATED");
}
public get uitextAwaitingCalculation() {
return this.intlService.localizeText("INFO_PARAMFIELD_AWAITING_CALCULATION");
}
/**
* Label d'une entrée du select des paramètres liés
*/
......
......@@ -99,7 +99,7 @@ export class ResultsGraphComponent implements AfterContentInit, Observer {
*/
public getChartAxisLabel(symbol: string) {
// 1. calculated param ?
if (this._results.calculatedParameter.symbol === symbol) {
if (this._results.calculatedParameter && this._results.calculatedParameter.symbol === symbol) {
return this._results.calculatedParameterHeader;
} else
// 2. variated param ?
......
......@@ -19,6 +19,9 @@ export class FormulaireCourbeRemous extends FormulaireBase {
super();
this._formSection = new FormDefSection(this);
this._formResult = new FormResultRemous(this);
// remove obsolete observer set by super()
this.removeObserver(this._formCompute);
this._formCompute = new FormComputeCourbeRemous(this, this._formSection, (this._formResult as FormResultRemous));
// default properties
this._props["methodeResolution"] = MethodeResolution.Trapezes;
......
......@@ -2,22 +2,14 @@ import { Observer } from "jalhyd";
import { SelectField } from "../../select-field";
import { FormulaireBase } from "./form-base";
import { NgParamInputComponent } from "../../../components/ngparam-input/ngparam-input.component";
import { FormResultFixedVar } from "../form-result-fixedvar";
import { FormComputeFixedVar } from "../form-compute-fixedvar";
export class FormulaireLechaptCalmon extends FormulaireBase implements Observer {
constructor() {
super();
this._formResult = new FormResultFixedVar(this, false);
this._formCompute = new FormComputeFixedVar(this, (this._formResult as FormResultFixedVar));
}
protected completeParse(json: {}) {
super.completeParse(json);
// abonnement au changement de valeur du select de matériau
this.getFormulaireNodeById("select_material").addObserver(this);
// abonnement au changement de valeur de l'un dex trois champs affectés par le changement de matériau
// abonnement au changement de valeur de l'un des trois champs affectés par le changement de matériau
this.getParamFromSymbol("L").addObserver(this);
this.getParamFromSymbol("M").addObserver(this);
this.getParamFromSymbol("N").addObserver(this);
......
......@@ -24,6 +24,9 @@ export class FormulaireParallelStructure extends FormulaireBase {
super();
this._formResult = new FormResultFixedVar(this, false);
this._formParallelStruct = new FormDefParallelStructures();
// remove obsolete observer set by super()
this.removeObserver(this._formCompute);
this._formCompute = new FormComputeParallelStructures(this, this._formParallelStruct, (this._formResult as FormResultFixedVar));
}
......
import { IObservable, Observer } from "jalhyd";
import { FormResultFixedVar } from "../form-result-fixedvar";
import { FormDefSection } from "../form-def-section";
import { FieldSet } from "../../fieldset";
import { FormComputeFixedVar } from "../form-compute-fixedvar";
import { FormulaireBase } from "./form-base";
export class FormulaireRegimeUniforme extends FormulaireBase implements Observer {
......@@ -12,8 +10,6 @@ export class FormulaireRegimeUniforme extends FormulaireBase implements Observer
constructor() {
super();
this._formSection = new FormDefSection(this);
this._formResult = new FormResultFixedVar(this, true);
this._formCompute = new FormComputeFixedVar(this, (this._formResult as FormResultFixedVar));
}
protected parseOptions(json: {}) {
......
import { IObservable } from "jalhyd";
import { IObservable, Nub } from "jalhyd";
import { FormResultSection } from "../form-result-section";
import { FormDefSection } from "../form-def-section";
......@@ -13,8 +13,12 @@ export class FormulaireSectionParametree extends FormulaireBase {
constructor() {
super();
this._formSection = new FormDefSection(this);
this._formResult = new FormResultSection(this, this._formSection);
this._formResult = new FormResultSection(this);
// remove obsolete observer set by super()
this.removeObserver(this._formCompute);
this._formCompute = new FormComputeSectionParametree(this, this._formSection, (this._formResult as FormResultSection));
// default properties
this._props["varCalc"] = "Hs";
}
......@@ -32,7 +36,15 @@ export class FormulaireSectionParametree extends FormulaireBase {
update(sender: IObservable, data: any) {
super.update(sender, data);
// super.update(sender, data);
if (sender instanceof Nub) {
switch (data.action) {
case "resultUpdated":
// forward Nub results update notification to FormCompute objects
this.notifyNubResultUpdated(sender);
break;
}
}
// changement de propriété du FieldSet contenant le select de choix du type de section
if (sender instanceof FieldSet && data.action === "propertyChange") {
......
......@@ -43,11 +43,7 @@ export class FormComputeFixedVar extends FormCompute {
}
protected compute() {
const nub: Nub = this._formBase.currentNub;
const computedParam: NgParameter = this.getComputedParameter();
const res: Result = this.runNubCalc(nub);
this.runNubCalc(this._formBase.currentNub);
this.reaffectResultComponents();
}
......
import { SectionParametree, acSection, Result, ParamDomain, ParamDefinition, ParamDomainValue } from "jalhyd";
import { SectionParametree, acSection, Result, ParamDefinition, Nub } from "jalhyd";
import { FormCompute } from "./form-compute";
import { NgParameter } from "../ngparam";
import { FormResult } from "./form-result";
import { FormDefSection } from "./form-def-section";
import { FormResultSection } from "./form-result-section";
import { VarResults } from "../../results/var-results";
import { SectionResults } from "../../results/section-results";
import { FormulaireDefinition } from "./form-definition";
import { FormulaireNode } from "../formulaire-node";
export class FormComputeSectionParametree extends FormCompute {
private tmpResult: Result;
constructor(formBase: FormulaireDefinition, private _formSection: FormDefSection, formResult: FormResult) {
constructor(formBase: FormulaireDefinition, private _formSection: FormDefSection, formResult: FormResultSection) {
super(formBase, formResult);
}
......@@ -30,119 +25,33 @@ export class FormComputeSectionParametree extends FormCompute {
return this._formSectionResult.sectionResults;
}
/**
* calcul de la section paramétrée dans le cas d'un paramètre à varier
* @param varParam paramètre à varier
*/
private doComputeSectionVar(varParam: NgParameter) {
this._formSectionResult.addSectionFixedParameters(false);
// paramètre à calculer en fonction du paramètre à varier
const computedParamInfo = this._formSection.getSectionComputedParam();
const sectNub: SectionParametree = this._formBase.currentNub as SectionParametree;
const sect: acSection = sectNub.section;
this._sectionResults.section = sect;
this._varResults.variatedParameter = varParam;
const computedParam: NgParameter = this.createParameter(computedParamInfo.symbol, this._formBase);
this._varResults.calculatedParameter = computedParam;
this._varResults.result = this.runNubCalc(sectNub);
this._varResults.update(false);
}
protected compute() {
const varParam = this._formSection.getSectionVariatedParameter();
if (varParam !== undefined) {
this.doComputeSectionVar(varParam);
return;
}
const sectNub: SectionParametree = this._formBase.currentNub as SectionParametree;
this.tmpResult = sectNub.CalcSerie(
undefined, // valeur initiale, non utilisée dans ce cas
undefined // variable à calculer, non utilisée
);
this.runNubCalc(this._formBase.currentNub);
this.reaffectResultComponents();
}
protected runNubCalc(nub: Nub, computedParam?: ParamDefinition): Result {
return nub.CalcSerie();
}
protected reaffectResultComponents() {
const sectNub: SectionParametree = this._formBase.currentNub as SectionParametree;
const sect: acSection = sectNub.section;
this._sectionResults.section = sect;
// résultats de section (avec le graphique de section)
this._sectionResults.result = this.tmpResult;
// résultats complémentaires des paramètres fixés
this._formSectionResult.addSectionFixedParameters(false);
this._formSectionResult.fixedResults.result = this.tmpResult;
}
/**
*
* @param calcType crée un NgParameter n'appartenant pas à un ComputeNode