CORPORATION: adding prevState and changed state display in the warehouse UI (#861)

This commit is contained in:
Caldwell 2023-10-23 10:48:06 +02:00 committed by GitHub
parent eed2c5d6d4
commit e992cb966a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 96 additions and 76 deletions

@ -26,11 +26,12 @@ interface CorporationInfo
| [issuedShares](./bitburner.corporationinfo.issuedshares.md) | | number | Amount of shares owned by public traders. Available for CEO buyback. | | [issuedShares](./bitburner.corporationinfo.issuedshares.md) | | number | Amount of shares owned by public traders. Available for CEO buyback. |
| [issueNewSharesCooldown](./bitburner.corporationinfo.issuenewsharescooldown.md) | | number | Cooldown until new shares can be issued | | [issueNewSharesCooldown](./bitburner.corporationinfo.issuenewsharescooldown.md) | | number | Cooldown until new shares can be issued |
| [name](./bitburner.corporationinfo.name.md) | | string | Name of the corporation | | [name](./bitburner.corporationinfo.name.md) | | string | Name of the corporation |
| [nextState](./bitburner.corporationinfo.nextstate.md) | | [CorpStateName](./bitburner.corpstatename.md) | <p>The next state to be processed.</p><p>I.e. when the state is PURCHASE, it means purchasing will occur during the next state transition.</p><p>Possible states are START, PURCHASE, PRODUCTION, EXPORT, SALE.</p> |
| [numShares](./bitburner.corporationinfo.numshares.md) | | number | Amount of shares owned by the CEO. | | [numShares](./bitburner.corporationinfo.numshares.md) | | number | Amount of shares owned by the CEO. |
| [prevState](./bitburner.corporationinfo.prevstate.md) | | [CorpStateName](./bitburner.corpstatename.md) | <p>The last state that got processed.</p><p>I.e. when that state is PURCHASE, it means purchasing just happened.</p><p>Possible states are START, PURCHASE, PRODUCTION, EXPORT, SALE.</p> |
| [public](./bitburner.corporationinfo.public.md) | | boolean | Indicating if the company is public | | [public](./bitburner.corporationinfo.public.md) | | boolean | Indicating if the company is public |
| [revenue](./bitburner.corporationinfo.revenue.md) | | number | Revenue per second this cycle | | [revenue](./bitburner.corporationinfo.revenue.md) | | number | Revenue per second this cycle |
| [sharePrice](./bitburner.corporationinfo.shareprice.md) | | number | Price of the shares | | [sharePrice](./bitburner.corporationinfo.shareprice.md) | | number | Price of the shares |
| [shareSaleCooldown](./bitburner.corporationinfo.sharesalecooldown.md) | | number | Cooldown until shares can be sold again | | [shareSaleCooldown](./bitburner.corporationinfo.sharesalecooldown.md) | | number | Cooldown until shares can be sold again |
| [state](./bitburner.corporationinfo.state.md) | | string | <p>The next state to be processed.</p><p>I.e. when the state is PURCHASE, it means purchasing will occur during the next state transition.</p><p>Possible states are START, PURCHASE, PRODUCTION, EXPORT, SALE.</p> |
| [totalShares](./bitburner.corporationinfo.totalshares.md) | | number | Total number of shares issued by this corporation. | | [totalShares](./bitburner.corporationinfo.totalshares.md) | | number | Total number of shares issued by this corporation. |

@ -1,8 +1,8 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. --> <!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CorporationInfo](./bitburner.corporationinfo.md) &gt; [state](./bitburner.corporationinfo.state.md) [Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CorporationInfo](./bitburner.corporationinfo.md) &gt; [nextState](./bitburner.corporationinfo.nextstate.md)
## CorporationInfo.state property ## CorporationInfo.nextState property
The next state to be processed. The next state to be processed.
@ -13,5 +13,5 @@ Possible states are START, PURCHASE, PRODUCTION, EXPORT, SALE.
**Signature:** **Signature:**
```typescript ```typescript
state: string; nextState: CorpStateName;
``` ```

@ -0,0 +1,17 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CorporationInfo](./bitburner.corporationinfo.md) &gt; [prevState](./bitburner.corporationinfo.prevstate.md)
## CorporationInfo.prevState property
The last state that got processed.
I.e. when that state is PURCHASE, it means purchasing just happened.
Possible states are START, PURCHASE, PRODUCTION, EXPORT, SALE.
**Signature:**
```typescript
prevState: CorpStateName;
```

@ -94,8 +94,8 @@ export class Corporation {
this.funds += amt; this.funds += amt;
} }
getState(): CorpStateName { getNextState(): CorpStateName {
return this.state.getState(); return this.state.nextName;
} }
storeCycles(numCycles: number): void { storeCycles(numCycles: number): void {
@ -106,7 +106,7 @@ export class Corporation {
if (this.storedCycles < 0) this.storedCycles = 0; if (this.storedCycles < 0) this.storedCycles = 0;
if (this.storedCycles >= corpConstants.gameCyclesPerCorpStateCycle) { if (this.storedCycles >= corpConstants.gameCyclesPerCorpStateCycle) {
const state = this.getState(); const state = this.getNextState();
const marketCycles = 1; const marketCycles = 1;
const gameCycles = marketCycles * corpConstants.gameCyclesPerCorpStateCycle; const gameCycles = marketCycles * corpConstants.gameCyclesPerCorpStateCycle;
this.storedCycles -= gameCycles; this.storedCycles -= gameCycles;
@ -171,7 +171,7 @@ export class Corporation {
this.updateSharePrice(); this.updateSharePrice();
} }
this.state.nextState(); this.state.incrementState();
// Handle "nextUpdate" resolvers after this update // Handle "nextUpdate" resolvers after this update
for (const resolve of CorporationResolvers.splice(0)) { for (const resolve of CorporationResolvers.splice(0)) {

@ -9,12 +9,14 @@ export class CorporationState {
// Get the name of the current state // Get the name of the current state
// NOTE: This does NOT return the number stored in the 'state' property, // NOTE: This does NOT return the number stored in the 'state' property,
// which is just an index for the array of all possible Corporation States. // which is just an index for the array of all possible Corporation States.
getState(): CorpStateName { get nextName(): CorpStateName {
return stateNames[this.state]; return stateNames[this.state];
} }
get prevName(): CorpStateName {
return stateNames[(this.state + (stateNames.length - 1)) % stateNames.length];
}
// Transition to the next state // Transition to the next state
nextState(): void { incrementState(): void {
this.state = (this.state + 1) % stateNames.length; this.state = (this.state + 1) % stateNames.length;
} }
@ -22,7 +24,6 @@ export class CorporationState {
toJSON(): IReviverValue { toJSON(): IReviverValue {
return Generic_toJSON("CorporationState", this); return Generic_toJSON("CorporationState", this);
} }
// Initializes a CorporationState object from a JSON save state. // Initializes a CorporationState object from a JSON save state.
static fromJSON(value: IReviverValue): CorporationState { static fromJSON(value: IReviverValue): CorporationState {
return Generic_fromJSON(CorporationState, value.data); return Generic_fromJSON(CorporationState, value.data);

@ -142,7 +142,7 @@ export class Division {
} }
process(marketCycles = 1, corporation: Corporation): void { process(marketCycles = 1, corporation: Corporation): void {
const state = corporation.state.getState(); const state = corporation.state.nextName;
//At the start of a cycle, store and reset revenue/expenses //At the start of a cycle, store and reset revenue/expenses
//Then calculate salaries and process the markets //Then calculate salaries and process the markets
if (state === "START") { if (state === "START") {
@ -264,7 +264,7 @@ export class Division {
//Process production, purchase, and import/export of materials //Process production, purchase, and import/export of materials
processMaterials(marketCycles = 1, corporation: Corporation): [number, number] { processMaterials(marketCycles = 1, corporation: Corporation): [number, number] {
const state = corporation.state.getState(); const state = corporation.state.nextName;
let revenue = 0; let revenue = 0;
let expenses = 0; let expenses = 0;
this.calculateProductionFactors(); this.calculateProductionFactors();
@ -717,7 +717,7 @@ export class Division {
/** Process product development and production/sale */ /** Process product development and production/sale */
processProducts(marketCycles = 1, corporation: Corporation): [number, number] { processProducts(marketCycles = 1, corporation: Corporation): [number, number] {
const state = corporation.state.getState(); const state = corporation.state.nextName;
let revenue = 0; let revenue = 0;
const expenses = 0; const expenses = 0;
@ -746,7 +746,7 @@ export class Division {
//Processes FINISHED products //Processes FINISHED products
processProduct(marketCycles = 1, product: Product, corporation: Corporation): number { processProduct(marketCycles = 1, product: Product, corporation: Corporation): number {
const state = corporation.state.getState(); const state = corporation.state.nextName;
let totalProfit = 0; let totalProfit = 0;
for (const [city, office] of getRecordEntries(this.offices)) { for (const [city, office] of getRecordEntries(this.offices)) {
const warehouse = this.warehouses[city]; const warehouse = this.warehouses[city];

@ -10,7 +10,7 @@ import { SmartSupplyModal } from "./modals/SmartSupplyModal";
import { ProductElem } from "./ProductElem"; import { ProductElem } from "./ProductElem";
import { MaterialElem } from "./MaterialElem"; import { MaterialElem } from "./MaterialElem";
import { MaterialInfo } from "../MaterialInfo"; import { MaterialInfo } from "../MaterialInfo";
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
import { formatBigNumber, formatMaterialSize } from "../../ui/formatNumber"; import { formatBigNumber, formatMaterialSize } from "../../ui/formatNumber";
import { Corporation } from "../Corporation"; import { Corporation } from "../Corporation";
@ -20,7 +20,7 @@ import { isRelevantMaterial } from "./Helpers";
import { IndustryProductEquation } from "./IndustryProductEquation"; import { IndustryProductEquation } from "./IndustryProductEquation";
import { purchaseWarehouse } from "../Actions"; import { purchaseWarehouse } from "../Actions";
import { useCorporation, useDivision } from "./Context"; import { useCorporation, useDivision } from "./Context";
import { gameCyclesPerCorpStateCycle } from "../data/Constants";
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip"; import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
interface WarehouseProps { interface WarehouseProps {
@ -57,30 +57,14 @@ function WarehouseRoot(props: WarehouseProps): React.ReactElement {
corp.funds = corp.funds - sizeUpgradeCost; corp.funds = corp.funds - sizeUpgradeCost;
props.rerender(); props.rerender();
} }
// -1 because as soon as it hits "full" it processes and resets to 0, *2 to double the size of the bar
// Next state which will be processed: const ticks = (gameCyclesPerCorpStateCycle - 1) * 2;
const state = corp.state.getState(); const nextState = corp.state.nextName;
let stateText; const prevState = corp.state.prevName.padStart(11);
switch (state) { const stateBar = createProgressBarText({
case "START": progress: Math.min(corp.storedCycles * 2, ticks) / ticks,
stateText = "Next state: Preparing"; totalTicks: ticks,
break; });
case "PURCHASE":
stateText = "Next state: Purchasing materials";
break;
case "PRODUCTION":
stateText = "Next state: Producing materials and/or products";
break;
case "SALE":
stateText = "Next state: Selling materials and/or products";
break;
case "EXPORT":
stateText = "Next state: Exporting materials and/or products";
break;
default:
console.error(`Invalid state: ${state}`);
break;
}
// Create React components for materials // Create React components for materials
const mats = []; const mats = [];
@ -160,9 +144,9 @@ function WarehouseRoot(props: WarehouseProps): React.ReactElement {
divisions. divisions.
</Typography> </Typography>
<br /> <br />
<Typography style={{ whiteSpace: "pre-wrap" }} className={classes.retainHeight}>
<Typography className={classes.retainHeight}>{stateText}</Typography> {prevState} {stateBar} {nextState}
</Typography>
{corp.unlocks.has(CorpUnlockName.SmartSupply) && ( {corp.unlocks.has(CorpUnlockName.SmartSupply) && (
<> <>
<Button onClick={() => setSmartSupplyOpen(true)}>Configure Smart Supply</Button> <Button onClick={() => setSmartSupplyOpen(true)}>Configure Smart Supply</Button>

@ -103,6 +103,7 @@ import { ContentFilePath } from "./Paths/ContentFile";
import { hasContractExtension } from "./Paths/ContractFilePath"; import { hasContractExtension } from "./Paths/ContractFilePath";
import { getRamCost } from "./Netscript/RamCostGenerator"; import { getRamCost } from "./Netscript/RamCostGenerator";
import { getEnumHelper } from "./utils/EnumHelper"; import { getEnumHelper } from "./utils/EnumHelper";
import { setDeprecatedProperties, deprecationWarning } from "./utils/DeprecationHelper";
export const enums: NSEnums = { export const enums: NSEnums = {
CityName, CityName,
@ -1807,30 +1808,3 @@ function getFunctionNames(obj: object, prefix: string): string[] {
} }
return functionNames; return functionNames;
} }
const deprecatedWarningsGiven = new Set();
function setDeprecatedProperties(
obj: object,
properties: Record<string, { identifier: string; message: string; value: any }>,
) {
for (const [name, info] of Object.entries(properties)) {
Object.defineProperty(obj, name, {
get: () => {
deprecationWarning(info.identifier, info.message);
return info.value;
},
set: (value: any) => (info.value = value),
enumerable: true,
});
}
}
function deprecationWarning(identifier: string, message: string) {
if (!deprecatedWarningsGiven.has(identifier)) {
deprecatedWarningsGiven.add(identifier);
Terminal.warn(`Accessed deprecated function or property: ${identifier}`);
Terminal.warn(`This is no longer supported usage and will be removed in a later version.`);
Terminal.warn(message);
Terminal.info(`This message can also appear for object properties when the object's values are iterated.`);
Terminal.info(`This message will only be shown once per game session for each deprecated item accessed.`);
}
}

@ -7,7 +7,7 @@ import { Warehouse } from "../Corporation/Warehouse";
import { Division } from "../Corporation/Division"; import { Division } from "../Corporation/Division";
import { Corporation, CorporationResolvers } from "../Corporation/Corporation"; import { Corporation, CorporationResolvers } from "../Corporation/Corporation";
import { cloneDeep, omit } from "lodash"; import { cloneDeep, omit } from "lodash";
import { setDeprecatedProperties } from "../utils/DeprecationHelper";
import { import {
Corporation as NSCorporation, Corporation as NSCorporation,
Division as NSDivision, Division as NSDivision,
@ -698,7 +698,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
getCorporation: (ctx) => () => { getCorporation: (ctx) => () => {
checkAccess(ctx); checkAccess(ctx);
const corporation = getCorporation(); const corporation = getCorporation();
return { const data = {
name: corporation.name, name: corporation.name,
funds: corporation.funds, funds: corporation.funds,
revenue: corporation.revenue, revenue: corporation.revenue,
@ -714,9 +714,18 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
dividendRate: corporation.dividendRate, dividendRate: corporation.dividendRate,
dividendTax: corporation.dividendTax, dividendTax: corporation.dividendTax,
dividendEarnings: corporation.getCycleDividends() / corpConstants.secondsPerMarketCycle, dividendEarnings: corporation.getCycleDividends() / corpConstants.secondsPerMarketCycle,
state: corporation.state.getState(), nextState: corporation.state.nextName,
prevState: corporation.state.prevName,
divisions: [...corporation.divisions.keys()], divisions: [...corporation.divisions.keys()],
}; };
setDeprecatedProperties(data, {
state: {
identifier: "ns.corporation.getCorporation().state",
message: "Use ns.corporation.getCorporation().nextState instead.",
value: corporation.state.nextName,
},
});
return data;
}, },
createCorporation: createCorporation:
(ctx) => (ctx) =>

@ -7686,7 +7686,13 @@ interface CorporationInfo {
* I.e. when the state is PURCHASE, it means purchasing will occur during the next state transition. * I.e. when the state is PURCHASE, it means purchasing will occur during the next state transition.
* *
* Possible states are START, PURCHASE, PRODUCTION, EXPORT, SALE. */ * Possible states are START, PURCHASE, PRODUCTION, EXPORT, SALE. */
state: string; nextState: CorpStateName;
/** The last state that got processed.
*
* I.e. when that state is PURCHASE, it means purchasing just happened.
*
* Possible states are START, PURCHASE, PRODUCTION, EXPORT, SALE. */
prevState: CorpStateName;
/** Array of all division names */ /** Array of all division names */
divisions: string[]; divisions: string[];
} }

@ -0,0 +1,28 @@
import { Terminal } from "../Terminal";
const deprecatedWarningsGiven = new Set();
export function setDeprecatedProperties(
obj: object,
properties: Record<string, { identifier: string; message: string; value: any }>,
) {
for (const [name, info] of Object.entries(properties)) {
Object.defineProperty(obj, name, {
get: () => {
deprecationWarning(info.identifier, info.message);
return info.value;
},
set: (value: any) => (info.value = value),
enumerable: true,
});
}
}
export function deprecationWarning(identifier: string, message: string) {
if (!deprecatedWarningsGiven.has(identifier)) {
deprecatedWarningsGiven.add(identifier);
Terminal.warn(`Accessed deprecated function or property: ${identifier}`);
Terminal.warn(`This is no longer supported usage and will be removed in a later version.`);
Terminal.warn(message);
Terminal.info(`This message can also appear for object properties when the object's values are iterated.`);
Terminal.info(`This message will only be shown once per game session for each deprecated item accessed.`);
}
}