summaryrefslogtreecommitdiff
path: root/gui/src/types/balanceToBudgetRatio.ts
diff options
context:
space:
mode:
Diffstat (limited to 'gui/src/types/balanceToBudgetRatio.ts')
-rw-r--r--gui/src/types/balanceToBudgetRatio.ts83
1 files changed, 83 insertions, 0 deletions
diff --git a/gui/src/types/balanceToBudgetRatio.ts b/gui/src/types/balanceToBudgetRatio.ts
new file mode 100644
index 0000000..2f8000c
--- /dev/null
+++ b/gui/src/types/balanceToBudgetRatio.ts
@@ -0,0 +1,83 @@
+import { Budget } from "./budget";
+import Currency from "./currency/currency";
+
+class BalanceToBudgetRatio {
+ toString(): string {
+ return this._ratio?.toFixed(2) ?? "";
+ }
+
+ public readonly recommendedAction: "arrears" | "save" | "spend" | null;
+ public readonly normalisedRatio: number | null;
+
+ private constructor(
+ private readonly _ratio: number | null,
+ private readonly _normalisationFactor: number,
+ ) {
+ if (this._ratio === null) {
+ this.normalisedRatio = null;
+ this.recommendedAction = null;
+ return;
+ }
+
+ this.normalisedRatio = this._ratio * this._normalisationFactor;
+
+ if (this._ratio < 0) {
+ this.recommendedAction = "arrears";
+ } else if (this._ratio >= 1) {
+ this.recommendedAction = "spend";
+ } else {
+ this.recommendedAction = "save";
+ }
+ }
+
+ static new(balance: Currency, budget: Budget | null) {
+ if (budget === null || budget.quantity === 0 || budget.quantity === -0) {
+ return null;
+ }
+
+ return new BalanceToBudgetRatio(
+ balance.valueOf() / budget.quantity.valueOf(),
+ 1,
+ );
+ }
+
+ static makeNormaliser(
+ ...balanceToBudgetRatios: (BalanceToBudgetRatio | null)[]
+ ): (r: BalanceToBudgetRatio | null) => BalanceToBudgetRatio {
+ const validRatios = balanceToBudgetRatios.filter(
+ (r) =>
+ r &&
+ r._ratio &&
+ !isNaN(r._ratio) &&
+ Infinity > r._ratio &&
+ -Infinity < r._ratio,
+ );
+
+ const maxAbsRatio = Math.max(
+ ...validRatios.map((r) => Math.abs(r?._ratio ?? 0)),
+ );
+
+ const normalisationFactor = 1 / maxAbsRatio;
+ return (r) =>
+ new BalanceToBudgetRatio(r?._ratio ?? null, normalisationFactor);
+ }
+
+ static compare(
+ lhs: BalanceToBudgetRatio | null,
+ rhs: BalanceToBudgetRatio | null,
+ ): number {
+ if (lhs === null || lhs._ratio === null) {
+ if (rhs === null || rhs._ratio === null) {
+ return 0;
+ }
+ return 1;
+ }
+ if (rhs === null || rhs._ratio === null) {
+ return -1;
+ }
+
+ return rhs._ratio - lhs._ratio;
+ }
+}
+
+export { BalanceToBudgetRatio };