-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFormulaTree.ts
More file actions
106 lines (87 loc) · 2.9 KB
/
FormulaTree.ts
File metadata and controls
106 lines (87 loc) · 2.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//Would be shorter and more efficient as procedural code, but I wanted to have the formula tree as an object
class FormulaTree {
constructor(private variables: Variable[]) { }
public addVariable(variable: Variable) {
}
public getVariable(name: String): Variable {
return new Variable("");
}
public getVariableInfo(name: String): Object {
return {};
}
public getDependentsForVariable(variable: String): Variable[] {
return [new Variable("")];
}
private calculateVariable(variable: Variable, dependentValues?: Object): Number {
if (!variable.getFormula()) return variable.getValue();
var formula = variable.getFormula() || "";
if (dependentValues) {
for (const [key, value] of Object.entries(dependentValues)) {
formula.replaceAll(key, value.toString());
}
}
var oFunction = new Function(formula);
try {
var result = new Number(oFunction());
}
catch (e) {
throw new Error("Invalid formula for variable " + variable.getName());
}
return result;
}
public resolveFormula(variable: Variable): Number {
if (!variable.hasDependents()) return variable.getValue();
else {
let formula = variable.getFormula();
if (formula) {
let dependents = variable.getDependents();
let dependentValues = {};
for (let i = 0; i < dependents.length; i++) {
let dependent = dependents[i];
dependentValues[dependent.getName()] = this.resolveFormula(dependent);
}
return this.calculateVariable(variable, dependentValues);
}
else return variable.getValue();
}
}
}
class Variable {
constructor(private name: string, private formula?: string, private resolved?: boolean, private dependents?: Variable[], private value?: Number, private info?: Object) {
if (!(this.hasDependents() && formula) && !this.value) throw new Error("Variable must have either a value or formula and dependent variables");
}
getInfo(): Object {
if (this.info) return this.info;
else return {};
}
setInfo(info: Object) {
this.info = info;
}
getValue(): Number {
if (this.value) return this.value;
else return 0;
}
setValue(value: Number) {
this.value = value;
}
getFormula(): string | undefined {
if (this.formula) return this.formula;
}
getDependents(): Variable[] {
if (this.dependents) return this.dependents;
else return [];
}
setDependents(dependents: Variable[]) {
this.dependents = dependents;
}
getName(): string {
return this.name;
}
setResolved(resolved: boolean) {
this.resolved = resolved;
}
hasDependents(): boolean {
if (this.dependents) return this.dependents.length > 0;
return false;
}
}