import Decimal from "break_eternity.js"; import { type PartialResources } from "../types"; export class ResourceSet { private items = new Map(); public static get zero(): ResourceSet { return new ResourceSet(); } public static from(source: PartialResources): ResourceSet { const inst = new ResourceSet(); inst.items = new Map(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; } }