From 733f2ccb5bf36b6f8128957c95ba4e477124e1ef Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:43:37 +0700 Subject: [PATCH] CORPORATION: Improve performance of cycle valuation (#1088) This PR is an alternative for PR #1085. It includes these changes: * Create a new property: numberOfOfficesAndWarehouses. It's used for calculating cycle valuation. * Hardcode 1.0079741404289038 instead of calculating Math.pow(1.1, 1 / 12). --- src/Corporation/Actions.ts | 7 ++++++- src/Corporation/Corporation.ts | 28 +++++++++++++++++++--------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index e77d44014..b68f38649 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -43,14 +43,16 @@ export function NewDivision(corporation: Corporation, industry: IndustryType, na type: industry, }), ); + corporation.numberOfOfficesAndWarehouses += 2; } } export function removeDivision(corporation: Corporation, name: string): number { const division = corporation.divisions.get(name); if (!division) throw new Error("There is no division called " + name); - const price = division.calculateRecoupableValue(); corporation.divisions.delete(name); + corporation.numberOfOfficesAndWarehouses -= getRecordValues(division.offices).length; + corporation.numberOfOfficesAndWarehouses -= getRecordValues(division.warehouses).length; // We also need to remove any exports that were pointing to the old division for (const otherDivision of corporation.divisions.values()) { @@ -63,6 +65,7 @@ export function removeDivision(corporation: Corporation, name: string): number { } } } + const price = division.calculateRecoupableValue(); corporation.gainFunds(price, "division"); return price; } @@ -79,6 +82,7 @@ export function purchaseOffice(corporation: Corporation, division: Division, cit city: city, size: corpConstants.officeInitialSize, }); + ++corporation.numberOfOfficesAndWarehouses; } export function IssueDividends(corporation: Corporation, rate: number): void { @@ -397,6 +401,7 @@ export function purchaseWarehouse(corp: Corporation, division: Division, city: C loc: city, size: corpConstants.warehouseInitialSize, }); + ++corp.numberOfOfficesAndWarehouses; } export function UpgradeWarehouseCost(warehouse: Warehouse, amt: number): number { diff --git a/src/Corporation/Corporation.ts b/src/Corporation/Corporation.ts index 20b043c29..800921ae7 100644 --- a/src/Corporation/Corporation.ts +++ b/src/Corporation/Corporation.ts @@ -19,6 +19,7 @@ import { JSONMap, JSONSet } from "../Types/Jsonable"; import { formatMoney } from "../ui/formatNumber"; import { isPositiveInteger } from "../types"; import { createEnumKeyedRecord, getRecordValues } from "../Types/Record"; +import { getKeyList } from "../utils/helpers/getKeyList"; export const CorporationPromise: PromisePair = { promise: null, resolve: null }; @@ -72,6 +73,9 @@ export class Corporation { state = new CorporationState(); + // This is used for calculating cycle valuation. + numberOfOfficesAndWarehouses = 0; + constructor(params: ICorporationParams = {}) { this.name = params.name || "The Corporation"; this.seedFunded = params.seedFunded ?? false; @@ -199,11 +203,6 @@ export class Corporation { assetDelta = (this.totalAssets - this.previousTotalAssets) / corpConstants.secondsPerMarketCycle; // Handle pre-totalAssets saves assetDelta ??= this.revenue - this.expenses; - const numberOfOfficesAndWarehouses = [...this.divisions.values()] - .map( - (division: Division) => getRecordValues(division.offices).length + getRecordValues(division.warehouses).length, - ) - .reduce((sum: number, currentValue: number) => sum + currentValue, 0); if (this.public) { // Account for dividends if (this.dividendRate > 0) { @@ -211,14 +210,16 @@ export class Corporation { } val = this.funds + assetDelta * 85e3; - val *= Math.pow(Math.pow(1.1, 1 / 12), numberOfOfficesAndWarehouses); + // Math.pow(1.1, 1 / 12) = 1.0079741404289038 + val *= Math.pow(1.0079741404289038, this.numberOfOfficesAndWarehouses); val = Math.max(val, 0); } else { val = 10e9 + this.funds / 3; if (assetDelta > 0) { val += assetDelta * 315e3; } - val *= Math.pow(Math.pow(1.1, 1 / 12), numberOfOfficesAndWarehouses); + // Math.pow(1.1, 1 / 12) = 1.0079741404289038 + val *= Math.pow(1.0079741404289038, this.numberOfOfficesAndWarehouses); val -= val % 1e6; //Round down to nearest million } if (val < 10e9) val = 10e9; // Base valuation @@ -460,14 +461,23 @@ export class Corporation { return; } + // Exclude numberOfOfficesAndWarehouses + static includedProperties = getKeyList(Corporation, { removedKeys: ["numberOfOfficesAndWarehouses"] }); + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { - return Generic_toJSON("Corporation", this); + return Generic_toJSON("Corporation", this, Corporation.includedProperties); } /** Initializes a Corporation object from a JSON save state. */ static fromJSON(value: IReviverValue): Corporation { - return Generic_fromJSON(Corporation, value.data); + const corporation = Generic_fromJSON(Corporation, value.data, Corporation.includedProperties); + // numberOfOfficesAndWarehouses is not in the included properties and must be calculated + for (const division of corporation.divisions.values()) { + corporation.numberOfOfficesAndWarehouses += getRecordValues(division.offices).length; + corporation.numberOfOfficesAndWarehouses += getRecordValues(division.warehouses).length; + } + return corporation; } }