idle-economy/engine/src/game/ResourceSet.ts

95 lines
2.9 KiB
TypeScript

import Decimal from "break_eternity.js";
import { type PartialResources } from "../types";
export class ResourceSet {
private items = new Map<string, Decimal>();
public static get zero(): ResourceSet {
return new ResourceSet();
}
public static from(source: PartialResources): ResourceSet {
const inst = new ResourceSet();
inst.items = new Map<string, Decimal>(Object.entries(source) as [string, Decimal][]);
return inst;
}
public clear(): void {
this.items.clear();
}
public clone(): ResourceSet {
return ResourceSet.from(this.toObject());
}
public keys(mergeWith?: ResourceSet): string[] {
const keys = Array.from(this.items.keys());
const mergeWithKeys = mergeWith ? mergeWith.keys() : [];
return [...keys, ...mergeWithKeys.filter((mk) => !keys.includes(mk))];
}
public get(key: string): Decimal {
return this.items.get(key) ?? Decimal.dZero;
}
public set(key: string, value: Decimal): void {
this.items.set(key, value);
}
public setMany(values: ResourceSet): void {
this.items.clear();
[...values.items.entries()].forEach(([k, v]) => this.items.set(k, v));
}
public get isZero(): boolean {
return this.predicate(this.keys(), (res) => this.get(res).eq(0));
}
public predicate(keys: string[], predicate: (res: string) => boolean): boolean {
return keys.every((res) => predicate(res));
}
public gte(arg: ResourceSet): boolean {
return this.predicate(this.keys(arg), (res) => this.get(res).gte(arg.get(res)));
}
public static transform(keys: string[], target: ResourceSet, predicate: (res: string) => Decimal): void {
for (const res of keys)
target.set(res, predicate(res));
}
public sum(arg: ResourceSet): ResourceSet {
const inst = new ResourceSet();
ResourceSet.transform(this.keys(arg), inst, (res) => this.get(res).plus(arg.get(res)));
return inst;
}
public add(arg: ResourceSet): void {
ResourceSet.transform(this.keys(arg), this, (res) => this.get(res).plus(arg.get(res)));
}
public remove(arg: ResourceSet): void {
ResourceSet.transform(this.keys(arg), this, (res) => this.get(res).minus(arg.get(res)));
}
public mul(factor: number): ResourceSet {
const inst = new ResourceSet();
ResourceSet.transform(this.keys(), inst, (res) => this.get(res).multiply(factor));
return inst;
}
public div(factor: number): ResourceSet {
const inst = new ResourceSet();
ResourceSet.transform(this.keys(), inst, (res) => this.get(res).divide(factor));
return inst;
}
public toString(): string {
return Array.from(this.items).map(([k, v]) => `${formatNumber(v)} ${k}`).join(', ');
}
public toObject(): PartialResources {
return Object.fromEntries(this.items) as PartialResources;
}
}