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).
This commit is contained in:
catloversg 2024-02-15 20:43:37 +07:00 committed by GitHub
parent dc7c9bb065
commit 733f2ccb5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 25 additions and 10 deletions

@ -43,14 +43,16 @@ export function NewDivision(corporation: Corporation, industry: IndustryType, na
type: industry, type: industry,
}), }),
); );
corporation.numberOfOfficesAndWarehouses += 2;
} }
} }
export function removeDivision(corporation: Corporation, name: string): number { export function removeDivision(corporation: Corporation, name: string): number {
const division = corporation.divisions.get(name); const division = corporation.divisions.get(name);
if (!division) throw new Error("There is no division called " + name); if (!division) throw new Error("There is no division called " + name);
const price = division.calculateRecoupableValue();
corporation.divisions.delete(name); 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 // We also need to remove any exports that were pointing to the old division
for (const otherDivision of corporation.divisions.values()) { 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"); corporation.gainFunds(price, "division");
return price; return price;
} }
@ -79,6 +82,7 @@ export function purchaseOffice(corporation: Corporation, division: Division, cit
city: city, city: city,
size: corpConstants.officeInitialSize, size: corpConstants.officeInitialSize,
}); });
++corporation.numberOfOfficesAndWarehouses;
} }
export function IssueDividends(corporation: Corporation, rate: number): void { export function IssueDividends(corporation: Corporation, rate: number): void {
@ -397,6 +401,7 @@ export function purchaseWarehouse(corp: Corporation, division: Division, city: C
loc: city, loc: city,
size: corpConstants.warehouseInitialSize, size: corpConstants.warehouseInitialSize,
}); });
++corp.numberOfOfficesAndWarehouses;
} }
export function UpgradeWarehouseCost(warehouse: Warehouse, amt: number): number { export function UpgradeWarehouseCost(warehouse: Warehouse, amt: number): number {

@ -19,6 +19,7 @@ import { JSONMap, JSONSet } from "../Types/Jsonable";
import { formatMoney } from "../ui/formatNumber"; import { formatMoney } from "../ui/formatNumber";
import { isPositiveInteger } from "../types"; import { isPositiveInteger } from "../types";
import { createEnumKeyedRecord, getRecordValues } from "../Types/Record"; import { createEnumKeyedRecord, getRecordValues } from "../Types/Record";
import { getKeyList } from "../utils/helpers/getKeyList";
export const CorporationPromise: PromisePair<CorpStateName> = { promise: null, resolve: null }; export const CorporationPromise: PromisePair<CorpStateName> = { promise: null, resolve: null };
@ -72,6 +73,9 @@ export class Corporation {
state = new CorporationState(); state = new CorporationState();
// This is used for calculating cycle valuation.
numberOfOfficesAndWarehouses = 0;
constructor(params: ICorporationParams = {}) { constructor(params: ICorporationParams = {}) {
this.name = params.name || "The Corporation"; this.name = params.name || "The Corporation";
this.seedFunded = params.seedFunded ?? false; this.seedFunded = params.seedFunded ?? false;
@ -199,11 +203,6 @@ export class Corporation {
assetDelta = (this.totalAssets - this.previousTotalAssets) / corpConstants.secondsPerMarketCycle; assetDelta = (this.totalAssets - this.previousTotalAssets) / corpConstants.secondsPerMarketCycle;
// Handle pre-totalAssets saves // Handle pre-totalAssets saves
assetDelta ??= this.revenue - this.expenses; 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) { if (this.public) {
// Account for dividends // Account for dividends
if (this.dividendRate > 0) { if (this.dividendRate > 0) {
@ -211,14 +210,16 @@ export class Corporation {
} }
val = this.funds + assetDelta * 85e3; 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); val = Math.max(val, 0);
} else { } else {
val = 10e9 + this.funds / 3; val = 10e9 + this.funds / 3;
if (assetDelta > 0) { if (assetDelta > 0) {
val += assetDelta * 315e3; 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 val -= val % 1e6; //Round down to nearest million
} }
if (val < 10e9) val = 10e9; // Base valuation if (val < 10e9) val = 10e9; // Base valuation
@ -460,14 +461,23 @@ export class Corporation {
return; return;
} }
// Exclude numberOfOfficesAndWarehouses
static includedProperties = getKeyList(Corporation, { removedKeys: ["numberOfOfficesAndWarehouses"] });
/** Serialize the current object to a JSON save state. */ /** Serialize the current object to a JSON save state. */
toJSON(): IReviverValue { toJSON(): IReviverValue {
return Generic_toJSON("Corporation", this); return Generic_toJSON("Corporation", this, Corporation.includedProperties);
} }
/** Initializes a Corporation object from a JSON save state. */ /** Initializes a Corporation object from a JSON save state. */
static fromJSON(value: IReviverValue): Corporation { 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;
} }
} }