break_eternity and eternal_notations. cmd line option for time
This commit is contained in:
parent
03d4948f64
commit
a89f9b8141
|
|
@ -1,11 +1,12 @@
|
|||
import Decimal from "break_eternity.js";
|
||||
import { ResourceNames, type PartialResources, type Resource } from "../types";
|
||||
|
||||
export class ResourceSet {
|
||||
private items = new Map<Resource, number>();
|
||||
private items = new Map<Resource, Decimal>();
|
||||
|
||||
public static from(source: PartialResources): ResourceSet {
|
||||
const inst = new ResourceSet();
|
||||
inst.items = new Map<Resource, number>(Object.entries(source) as [Resource, number][]);
|
||||
inst.items = new Map<Resource, Decimal>(Object.entries(source) as [Resource, Decimal][]);
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
|
@ -13,11 +14,11 @@ export class ResourceSet {
|
|||
return ResourceSet.from(this.toObject());
|
||||
}
|
||||
|
||||
public get(key: Resource): number {
|
||||
return this.items.get(key) ?? 0;
|
||||
public get(key: Resource): Decimal {
|
||||
return this.items.get(key) ?? Decimal.dZero;
|
||||
}
|
||||
|
||||
public set(key: Resource, value: number): void {
|
||||
public set(key: Resource, value: Decimal): void {
|
||||
this.items.set(key, value);
|
||||
}
|
||||
|
||||
|
|
@ -26,31 +27,31 @@ export class ResourceSet {
|
|||
}
|
||||
|
||||
public gte(arg: ResourceSet): boolean {
|
||||
return this.predicate((res) => this.get(res) >= arg.get(res));
|
||||
return this.predicate((res) => this.get(res).gte(arg.get(res)));
|
||||
}
|
||||
|
||||
public static transform(target: ResourceSet, predicate: (res: Resource) => number): void {
|
||||
public static transform(target: ResourceSet, predicate: (res: Resource) => Decimal): void {
|
||||
for (const res of ResourceNames)
|
||||
target.set(res, predicate(res));
|
||||
}
|
||||
|
||||
public sum(arg: ResourceSet): ResourceSet {
|
||||
const inst = new ResourceSet();
|
||||
ResourceSet.transform(inst, (res) => this.get(res) + arg.get(res));
|
||||
ResourceSet.transform(inst, (res) => this.get(res).plus(arg.get(res)));
|
||||
return inst;
|
||||
}
|
||||
|
||||
public add(arg: ResourceSet): void {
|
||||
ResourceSet.transform(this, (res) => this.get(res) + arg.get(res));
|
||||
ResourceSet.transform(this, (res) => this.get(res).plus(arg.get(res)));
|
||||
}
|
||||
|
||||
public remove(arg: ResourceSet): void {
|
||||
ResourceSet.transform(this, (res) => this.get(res) - arg.get(res));
|
||||
ResourceSet.transform(this, (res) => this.get(res).minus(arg.get(res)));
|
||||
}
|
||||
|
||||
public times(factor: number): ResourceSet {
|
||||
const inst = new ResourceSet();
|
||||
ResourceSet.transform(inst, (res) => this.get(res) * factor);
|
||||
ResourceSet.transform(inst, (res) => this.get(res).multiply(factor));
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Decimal from 'break_eternity.js';
|
||||
import { Game } from './game';
|
||||
import type { ResourceGeneratorRule } from './rules';
|
||||
import type { PartialResources, Resource } from './types';
|
||||
import type { PartialResources, Resource, Resources } from './types';
|
||||
|
||||
export * from './types';
|
||||
export * from './rules';
|
||||
|
|
@ -33,9 +34,9 @@ function simpleResGen(params: SimpleResGenParams): ResourceGeneratorRule {
|
|||
Object.entries(p)
|
||||
.map(([res, rp]) => [
|
||||
res,
|
||||
(rp.offset ?? 0) + Math.pow(lvl, rp.power ?? 1) * (rp.factor ?? 0),
|
||||
new Decimal((rp.offset ?? 0) + Math.pow(lvl, rp.power ?? 1) * (rp.factor ?? 0)),
|
||||
])
|
||||
);
|
||||
) as Resources;
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -60,7 +61,7 @@ export function makeGame(): Game {
|
|||
generation: { RED: { offset: 3, power: 1.5, factor: 1 } },
|
||||
openPrice: { RED: { offset: 10, power: 2.1, factor: 10 } }
|
||||
}),
|
||||
...['orange', 'yellow', 'green', 'cyan', 'blue', 'violet', ...Array(20)]
|
||||
...['orange', 'yellow', 'green', 'cyan', 'blue', 'violet']
|
||||
.map((color, idx) => simpleResGen({
|
||||
name: color,
|
||||
period: idx + 2,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import Decimal from "break_eternity.js";
|
||||
|
||||
export const ResourceNames = ['RED'] as const;
|
||||
export type Resource = (typeof ResourceNames)[number];
|
||||
|
||||
export type Resources = Record<Resource, number>;
|
||||
export type PartialResources = Partial<Record<Resource, number>>;
|
||||
export type Resources = Record<Resource, Decimal>;
|
||||
export type PartialResources = Partial<Resources>;
|
||||
|
|
|
|||
|
|
@ -2023,6 +2023,13 @@
|
|||
"@babel/types": "^7.28.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/command-line-args": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.3.tgz",
|
||||
"integrity": "sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
|
||||
|
|
@ -2424,6 +2431,15 @@
|
|||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/array-back": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz",
|
||||
"integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
|
|
@ -2576,6 +2592,29 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/command-line-args": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.1.tgz",
|
||||
"integrity": "sha512-Jr3eByUjqyK0qd8W0SGFW1nZwqCaNCtbXjRo2cRJC1OYxWl3MZ5t1US3jq+cO4sPavqgw4l9BMGX0CBe+trepg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"array-back": "^6.2.2",
|
||||
"find-replace": "^5.0.2",
|
||||
"lodash.camelcase": "^4.3.0",
|
||||
"typical": "^7.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@75lb/nature": "latest"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@75lb/nature": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
|
|
@ -2904,6 +2943,16 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eternal_notations": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eternal_notations/-/eternal_notations-1.1.1.tgz",
|
||||
"integrity": "sha512-o4Pw4SyYh8j+vcPEID6B1kwo9T5qEbE4ld//297g8Rli0ZBVBGa93JWt3G5RetLL7nUO3x/u3oaZC1hDM13mgA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"break_eternity.js": "^2.1.0",
|
||||
"lru_cache": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
|
|
@ -2956,6 +3005,23 @@
|
|||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/find-replace": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz",
|
||||
"integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@75lb/nature": "latest"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@75lb/nature": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/find-up": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
||||
|
|
@ -3527,6 +3593,12 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
"integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||
|
|
@ -3534,6 +3606,12 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lru_cache": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lru_cache/-/lru_cache-1.0.2.tgz",
|
||||
"integrity": "sha512-gssVsWiGr3hdoJtlpY21bVrN+zDDzqIIi0Fdktn6mzw2IaKENO8gyTiwawLuGWu/ecRUnxBot4ilr0Uxtk6Stw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
|
|
@ -4145,6 +4223,15 @@
|
|||
"typescript": ">=4.8.4 <6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/typical": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz",
|
||||
"integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.16.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||
|
|
@ -4354,7 +4441,11 @@
|
|||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@formatjs/intl-durationformat": "^0.10.1",
|
||||
"@idle-economy/engine": "*"
|
||||
"@idle-economy/engine": "*",
|
||||
"command-line-args": "^6.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/command-line-args": "^5.2.3"
|
||||
}
|
||||
},
|
||||
"simulator/node_modules/@formatjs/ecma402-abstract": {
|
||||
|
|
@ -4400,6 +4491,7 @@
|
|||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@idle-economy/engine": "*",
|
||||
"eternal_notations": "^1.1.1",
|
||||
"mobx": "^6.15.0",
|
||||
"mobx-react-lite": "^4.1.1",
|
||||
"react": "^19.2.0",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@
|
|||
"license": "ISC",
|
||||
"type": "commonjs",
|
||||
"dependencies": {
|
||||
"@formatjs/intl-durationformat": "^0.10.1",
|
||||
"@idle-economy/engine": "*",
|
||||
"@formatjs/intl-durationformat": "^0.10.1"
|
||||
"command-line-args": "^6.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/command-line-args": "^5.2.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ const durationFormat = new DurationFormat("en", { style: "short" });
|
|||
|
||||
export type SimulationStats = {
|
||||
actions: Action[],
|
||||
finalTime: number;
|
||||
finalSnapshot: GameSnapshot,
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +51,7 @@ export class Simulator {
|
|||
time += deltaTime;
|
||||
}
|
||||
|
||||
stats.finalTime = time;
|
||||
stats.finalSnapshot = this.makeGameSnapshot();
|
||||
|
||||
this.log(time, "done");
|
||||
|
|
@ -82,8 +84,8 @@ export class Simulator {
|
|||
lastTime = action.time;
|
||||
maxDeltaTime = Math.max(maxDeltaTime, deltaTime);
|
||||
}
|
||||
this.log(0, `max action wait fime is ${maxDeltaTime}`)
|
||||
this.log(0, `final data:: ${JSON.stringify(stats.finalSnapshot, undefined, 2)}`);
|
||||
this.log(stats.finalTime, `max action wait fime is ${maxDeltaTime}`)
|
||||
this.log(stats.finalTime, `final data: ${JSON.stringify(stats.finalSnapshot, undefined, 2)}`);
|
||||
}
|
||||
|
||||
private logResources(time: number, resources: ResourceSet): void {
|
||||
|
|
|
|||
|
|
@ -1,16 +1,21 @@
|
|||
import { makeGame } from '@idle-economy/engine';
|
||||
import { Simulator } from './Simulator'
|
||||
import { Player } from './player/Player';
|
||||
import commandLineArgs from 'command-line-args'
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
// Clean up resources and exit
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
const optionDefinitions: commandLineArgs.OptionDefinition[] = [
|
||||
{ name: 'time', alias: 't', type: Number, defaultValue: 60 },
|
||||
];
|
||||
const options = commandLineArgs(optionDefinitions);
|
||||
|
||||
const game = makeGame();
|
||||
|
||||
const player = new Player(game);
|
||||
|
||||
const simulator = new Simulator(player);
|
||||
simulator.simulate(3600);
|
||||
simulator.simulate(options.time);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@idle-economy/engine": "*",
|
||||
"eternal_notations": "^1.1.1",
|
||||
"mobx": "^6.15.0",
|
||||
"mobx-react-lite": "^4.1.1",
|
||||
"react": "^19.2.0",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { root } from './state/Root';
|
|||
import { Page } from './Page';
|
||||
|
||||
import './App.scss'
|
||||
import type { ChangeEvent } from 'react';
|
||||
|
||||
function now(): number {
|
||||
return (performance.now() + performance.timeOrigin) / 1000;
|
||||
|
|
@ -36,12 +37,21 @@ export const App = observer(function () {
|
|||
root.tick(1 / 60);
|
||||
}
|
||||
|
||||
function handleNumberNotationChange(event: ChangeEvent<HTMLSelectElement, HTMLSelectElement>): void {
|
||||
root.setNumberNotationName(event.target.value);
|
||||
}
|
||||
|
||||
// useEffect(() => {
|
||||
// gameLoop();
|
||||
// }, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>Notation:
|
||||
<select onChange={handleNumberNotationChange} value={root.numberNotationName}>
|
||||
{root.availableNotationNames.map((n) => <option key={n} value={n}>{n}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
<Page />
|
||||
{/* <button onClick={handleTickClick}>tick</button> */}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ export const ResourcesView = function (props: Props) {
|
|||
<>
|
||||
<span className="resources">
|
||||
{
|
||||
Object.entries(props.resources).map(([res, value]) => <span style={{ color: res }}>{formatNumber(value)}</span>)
|
||||
Object.entries(props.resources).map(
|
||||
([res, value]) => <span key={res} style={{ color: res }}>{formatNumber(value)}</span>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { makeGame, ResourceGenerator, ResourceSet } from "@idle-economy/engine";
|
||||
import { makeAutoObservable } from "mobx";
|
||||
import { Notation, Presets } from 'eternal_notations';
|
||||
|
||||
export class Root {
|
||||
|
||||
|
|
@ -8,8 +9,13 @@ export class Root {
|
|||
public resources: ResourceSet = new ResourceSet();
|
||||
public generators: ResourceGenerator[] = [];
|
||||
|
||||
public readonly availableNotationNames: string[] = Object.keys(Presets).filter((n: any) => !!(Presets as any)[n].name);
|
||||
public numberNotationName: keyof typeof Presets = 'Standard';
|
||||
public numberNotation: Notation = Presets.Standard;
|
||||
|
||||
constructor() {
|
||||
this.copyGame();
|
||||
this.setNumberNotation();
|
||||
|
||||
makeAutoObservable(this);
|
||||
}
|
||||
|
|
@ -23,6 +29,16 @@ export class Root {
|
|||
this.resources = this.game.resources;
|
||||
this.generators = this.game.generators;
|
||||
}
|
||||
|
||||
public setNumberNotationName(value: string | keyof typeof Presets): void {
|
||||
this.numberNotationName = value as keyof typeof Presets;
|
||||
this.setNumberNotation();
|
||||
this.numberNotation.name
|
||||
}
|
||||
|
||||
private setNumberNotation() {
|
||||
this.numberNotation = Presets[this.numberNotationName] as Notation;
|
||||
}
|
||||
}
|
||||
|
||||
export const root = new Root();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
export function formatNumber(value: number): string {
|
||||
return (Math.round(value * 10 ** 2) / 10 ** 2).toPrecision(2);
|
||||
import type Decimal from 'break_eternity.js';
|
||||
import { root } from '../state/Root';
|
||||
|
||||
export function formatNumber(value: Decimal): string {
|
||||
return root.numberNotation.format(value);
|
||||
}
|
||||
Loading…
Reference in New Issue