-
francois.grand authoredfrancois.grand authored
ngparam.ts 9.42 KiB
import { ParamDefinition, Pair, ParamDomain } from "jalhyd";
import { InputField } from "./input-field";
import { Dependency } from "./dependency/dependency";
import { DependencyConditionType } from "./dependency/dependency-condition";
import { ValueDependencyCondition } from "./dependency/value-dependency-condition";
import { Observable, IObservable, Observer } from "../services/observer";
import { FormulaireDefinition } from "./definition/form-definition";
import { ApplicationSetupService } from "../services/app-setup/app-setup.service";
export enum ParamRadioConfig {
/**
* pas de radio, paramètre modifiable à la main uniquement
*/
FIX,
/**
* boutons radio "paramètre fixé" et "paramètre à varier"
*/
VAR,
/**
* boutons radio "paramètre fixé", "paramètre à varier" et "paramètre à calculer"
*/
CAL
};
/**
* mode de génération des valeurs d'entrée lors d'un calcul avec plusieurs valeurs
*/
export enum ParamValueMode {
/**
* min, max, pas
*/
MINMAX,
/**
* liste de valeurs discrètes
*/
LISTE
}
/**
* classe englobante de ParamDefinition (champs supplémentaires pour l'affichage, radio boutons, ...)
*/
export class NgParameter extends InputField { // implements IObservable {
public unit: string;
public radioConfig: ParamRadioConfig;
public radioState: ParamRadioConfig;
public isDefault: boolean = false; // archi bug du langage ! si on relit cette propriété sans l'avoir modifiée entre-temps, elle vaut undefined !
/**
* mode de génération des valeurs : min/max, liste, ...
*/
private _valueMode: ParamValueMode = ParamValueMode.MINMAX;
/**
* valeur min dans le cas ParamRadioConfig.VAR && ParamValueMode.MINMAX
*/
private _minValue: number = undefined;
/**
* valeur max dans le cas ParamRadioConfig.VAR && ParamValueMode.MINMAX
*/
private _maxValue: number = undefined;
/**
* pas de progression dans le cas ParamRadioConfig.VAR && ParamValueMode.MINMAX
*/
private _stepValue: number = undefined;
/**
* liste de valeurs dans le cas ParamRadioConfig.VAR && ParamValueMode.LISTE
*/
private _valueList: number[];
/**
* implémentation par délégation de IObservable
*/
private _observable: Observable;
constructor(private _paramDef: ParamDefinition, isTmpl = false) {
super(isTmpl);
this._observable = new Observable();
}
get symbol(): string {
return this._paramDef.symbol;
}
get domain(): ParamDomain {
return this._paramDef.getDomain();
}
public getValue() {
return this._paramDef.v;
}
public setValue(val: number) {
this._paramDef.v = val;
// this.notifyObservers(
// {
// "action": "value",
// "value": val
// }
// )
}
get isDefined(): boolean {
return this._paramDef.isDefined;
}
public checkValue(val: number) {
this._paramDef.checkValue(val);
}
public checkList(l: number[]) {
for (let e of l)
this.checkValue(e);
}
public get valueMode() {
return this._valueMode;
}
public set valueMode(m: ParamValueMode) {
// undefined si on clique en dehors du select après l'avoir ouvert (cad sans avoir fait de sélection)
// et au même niveau, cad à côté du bouton et non à côté du menu déroulant
if (m != undefined)
this._valueMode = m;
}
/**
* vérifie si un min/max est valide par rapport au domaine de définition
*/
private isMinMaxDomainValid(v: number): boolean {
if (v == undefined)
return false;
if (this._valueMode == ParamValueMode.MINMAX)
try {
this.checkValue(v);
}
catch (e) {
return false;
}
return true;
}
private checkMinMax(min: number, max: number): boolean {
return this.isMinMaxDomainValid(min) && this.isMinMaxDomainValid(max) && (min < max);
}
public checkMin(min: number): boolean {
return this.isMinMaxDomainValid(min) && (min < this._maxValue);
}
public checkMax(max: number): boolean {
return this.isMinMaxDomainValid(max) && (this._minValue < max);
}
public get isMinMaxValid(): boolean {
return this.checkMinMax(this._minValue, this._maxValue);
}
public get minValue() {
return this._minValue;
}
public set minValue(v: number) {
this._minValue = v;
}
public get maxValue() {
return this._maxValue;
}
public set maxValue(v: number) {
this._maxValue = v;
}
public checkStep(step: number): boolean {
return this.isMinMaxValid && this.stepRefValue.intervalHasValue(step);
}
public get stepRefValue(): Pair {
return new Pair(1e-9, this._maxValue - this._minValue);
}
public get stepValue() {
return this._stepValue;
}
public set stepValue(v: number) {
this._stepValue = v;
}
public get valueList() {
return this._valueList;
}
public set valueList(l: number[]) {
this._valueList = l;
}
private get isListValid(): boolean {
if (this._valueList == undefined)
return false;
for (let v of this._valueList)
try {
this.checkValue(v);
}
catch (e) {
return false;
}
return true;
}
private get isRangeValid(): boolean {
switch (this._valueMode) {
case ParamValueMode.LISTE:
return this.isListValid;
case ParamValueMode.MINMAX:
return this.checkStep(this._stepValue);
}
throw "NgParameter.isRangeValid() : valeur " + this._valueMode + " de ParamValueMode non prise en compte";
}
private get isValueValid(): boolean {
try {
const v = this._paramDef.getValue();
this._paramDef.checkValue(v);
return true;
}
catch (e) {
return false;
}
}
public get isValid() {
switch (this.radioState) {
case ParamRadioConfig.FIX:
return this.isValueValid;
case ParamRadioConfig.VAR:
return this.isRangeValid;
case ParamRadioConfig.CAL:
return true;
}
throw "NgParameter.isValid() : valeur de ParamRadioConfig non prise en compte";
}
private static getRadioConfig(s: string) {
if (s == "fix")
return ParamRadioConfig.FIX;
if (s == "var")
return ParamRadioConfig.VAR;
if (s == "cal")
return ParamRadioConfig.CAL;
throw "invalid parameter radio configuration " + s;
}
public parseConfig(json: {}, data?: {}) {
const appSetupService: ApplicationSetupService = data["appSetupService"];
const radioConfig: string = data["radioConfig"];
this._confId = json["id"];
this.unit = json["unit"];
if (this.symbol == "Pr")
var val = appSetupService.computePrecision;
else
val = json["value"];
if (val != undefined)
this.setValue(+val);
this.radioConfig = NgParameter.getRadioConfig(radioConfig);
this.radioState = ParamRadioConfig.FIX;
this.isDefault = false; // malgré le fait qu'il soit initialisé dans la déclaration de la classe NgParam à false, quand on relit sa valeur, il vaut undefined (merci Microsoft)
}
protected verifyDependency(d: Dependency): boolean {
switch (d.masterCondition.type) {
case DependencyConditionType.HasValue:
{
let mc: ValueDependencyCondition = <ValueDependencyCondition>d.masterCondition;
return this.getValue() === mc.value;
}
case DependencyConditionType.IsVariable:
return this.radioState == ParamRadioConfig.VAR;
default:
throw "NgParameter.verifyDependency() : type de condition '" + DependencyConditionType[d.masterCondition.type] + "' non pris en charge";
}
}
/**
* copie des membres
*/
protected copyMembers(n: NgParameter) {
super.copyMembers(n);
n.unit = this.unit;
n.radioConfig = this.radioConfig;
n.radioState = this.radioState;
n.isDefault = this.isDefault;
n._valueMode = this.valueMode;
n._minValue = this._minValue;
n._maxValue = this._maxValue;
n._stepValue = this._stepValue;
if (this._valueList != undefined)
n._valueList = this._valueList.slice(0); // copie
}
/**
* crée une nouvelle instance
*/
protected clone(): NgParameter {
return new NgParameter(this._paramDef.clone());
}
// // interface IObservable
// /**
// * ajoute un observateur à la liste
// */
// public addObserver(o: Observer) {
// this._observable.addObserver(o);
// }
// /**
// * supprime un observateur de la liste
// */
// public removeObserver(o: Observer) {
// this._observable.removeObserver(o);
// }
// /**
// * notifie un événement aux observateurs
// */
// public notifyObservers(data: any) {
// this._observable.notifyObservers(data, this);
// }
}