diff --git a/src/Corporation/Corporation.tsx b/src/Corporation/Corporation.tsx index d14d750d6..b6acdadfa 100644 --- a/src/Corporation/Corporation.tsx +++ b/src/Corporation/Corporation.tsx @@ -45,7 +45,9 @@ export class Corporation { upgrades: number[]; upgradeMultipliers: number[]; - avgProfit = 0; + cycleValuation = 0; + valuationsList = [0]; + valuation = 0; state = new CorporationState(); @@ -108,8 +110,8 @@ export class Corporation { this.expenses = this.expenses + ind.lastCycleExpenses; }); const profit = this.revenue - this.expenses; - this.avgProfit = - (this.avgProfit * (CorporationConstants.AvgProfitLength - 1) + profit) / CorporationConstants.AvgProfitLength; + this.cycleValuation = this.determineCycleValuation(); + this.determineValuation(); const cycleProfit = profit * (marketCycles * CorporationConstants.SecsPerMarketCycle); if (isNaN(this.funds) || this.funds === Infinity || this.funds === -Infinity) { dialogBoxCreate( @@ -166,9 +168,9 @@ export class Corporation { return Math.pow(dividends, 1 - this.dividendTax); } - determineValuation(): number { + determineCycleValuation(): number { let val, - profit = this.avgProfit; + profit = this.revenue - this.expenses; if (this.public) { // Account for dividends if (this.dividendRate > 0) { @@ -182,19 +184,25 @@ export class Corporation { val = 10e9 + Math.max(this.funds, 0) / 3; //Base valuation if (profit > 0) { val += profit * 315e3; - val *= Math.pow(1.1, this.divisions.length); - } else { - val = 10e9 * Math.pow(1.1, this.divisions.length); } + val *= Math.pow(1.1, this.divisions.length); val -= val % 1e6; //Round down to nearest millionth } return val * BitNodeMultipliers.CorporationValuation; } + determineValuation(): void { + this.valuationsList.push(this.cycleValuation); //Add current valuation to the list + if (this.valuationsList.length > CorporationConstants.ValuationLength) this.valuationsList.shift(); + let val = this.valuationsList.reduce((a, b) => a + b); //Calculate valuations sum + val /= CorporationConstants.ValuationLength; //Calculate the average + this.valuation = val; + } + getTargetSharePrice(): number { // Note: totalShares - numShares is not the same as issuedShares because // issuedShares does not account for private investors - return this.determineValuation() / (2 * (this.totalShares - this.numShares) + 1); + return this.valuation / (2 * (this.totalShares - this.numShares) + 1); } updateSharePrice(): void { @@ -243,7 +251,7 @@ export class Corporation { sharesSold += sharesUntilUpdate; // Calculate what new share price would be - sharePrice = this.determineValuation() / (2 * (this.totalShares + sharesSold - this.numShares)); + sharePrice = this.valuation / (2 * (this.totalShares + sharesSold - this.numShares)); } } diff --git a/src/Corporation/ICorporation.ts b/src/Corporation/ICorporation.ts index 66c575fda..4165d48a8 100644 --- a/src/Corporation/ICorporation.ts +++ b/src/Corporation/ICorporation.ts @@ -25,6 +25,7 @@ export interface ICorporation { issuedShares: number; sharePrice: number; storedCycles: number; + valuation: number; unlockUpgrades: number[]; upgrades: number[]; @@ -36,7 +37,8 @@ export interface ICorporation { getState(): string; storeCycles(numCycles: number): void; process(player: IPlayer): void; - determineValuation(): number; + determineValuation(): void; + determineCycleValuation(): number; getTargetSharePrice(): number; updateSharePrice(): void; immediatelyUpdateSharePrice(): void; diff --git a/src/Corporation/data/Constants.ts b/src/Corporation/data/Constants.ts index 5c4fa3f0d..e3ef5757e 100644 --- a/src/Corporation/data/Constants.ts +++ b/src/Corporation/data/Constants.ts @@ -32,7 +32,7 @@ export const CorporationConstants: { AllResearch: string[]; FundingRoundShares: number[]; FundingRoundMultiplier: number[]; - AvgProfitLength: number; + ValuationLength: number; } = { INITIALSHARES: 1e9, //Total number of shares you have at your company SHARESPERPRICEUPDATE: 1e6, //When selling large number of shares, price is dynamically updated for every batch of this amount @@ -153,5 +153,5 @@ export const CorporationConstants: { FundingRoundShares: [0.1, 0.35, 0.25, 0.2], FundingRoundMultiplier: [4, 3, 3, 2.5], - AvgProfitLength: 1, + ValuationLength: 5, }; diff --git a/src/Corporation/ui/Overview.tsx b/src/Corporation/ui/Overview.tsx index 2093db672..1dc811f0c 100644 --- a/src/Corporation/ui/Overview.tsx +++ b/src/Corporation/ui/Overview.tsx @@ -244,7 +244,7 @@ function BribeButton(): React.ReactElement { const corp = useCorporation(); const [open, setOpen] = useState(false); const canBribe = - corp.determineValuation() >= CorporationConstants.BribeThreshold && + corp.valuation >= CorporationConstants.BribeThreshold && player.factions.filter((f) => Factions[f].getInfo().offersWork()).length > 0; function openBribe(): void { diff --git a/src/Corporation/ui/modals/FindInvestorsModal.tsx b/src/Corporation/ui/modals/FindInvestorsModal.tsx index a6ee81ca6..454bba47b 100644 --- a/src/Corporation/ui/modals/FindInvestorsModal.tsx +++ b/src/Corporation/ui/modals/FindInvestorsModal.tsx @@ -16,7 +16,7 @@ interface IProps { // Create a popup that lets the player manage exports export function FindInvestorsModal(props: IProps): React.ReactElement { const corporation = useCorporation(); - const val = corporation.determineValuation(); + const val = corporation.valuation; if ( corporation.fundingRound >= CorporationConstants.FundingRoundShares.length || corporation.fundingRound >= CorporationConstants.FundingRoundMultiplier.length diff --git a/src/Corporation/ui/modals/GoPublicModal.tsx b/src/Corporation/ui/modals/GoPublicModal.tsx index 07a64f4dc..f1b16addb 100644 --- a/src/Corporation/ui/modals/GoPublicModal.tsx +++ b/src/Corporation/ui/modals/GoPublicModal.tsx @@ -19,10 +19,10 @@ interface IProps { export function GoPublicModal(props: IProps): React.ReactElement { const corp = useCorporation(); const [shares, setShares] = useState(NaN); - const initialSharePrice = corp.determineValuation() / corp.totalShares; + const initialSharePrice = corp.valuation / corp.totalShares; function goPublic(): void { - const initialSharePrice = corp.determineValuation() / corp.totalShares; + const initialSharePrice = corp.valuation / corp.totalShares; if (isNaN(shares)) { dialogBoxCreate("Invalid value for number of issued shares"); return; diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts index 865d0fe0c..6bbf10fdf 100644 --- a/src/NetscriptFunctions/Corporation.ts +++ b/src/NetscriptFunctions/Corporation.ts @@ -146,7 +146,7 @@ export function NetscriptCorporation(): InternalAPI { shares: 0, round: corporation.fundingRound + 1, // Make more readable }; // Don't throw an error here, no reason to have a second function to check if you can get investment. - const val = corporation.determineValuation(); + const val = corporation.valuation; const percShares = CorporationConstants.FundingRoundShares[corporation.fundingRound]; const roundMultiplier = CorporationConstants.FundingRoundMultiplier[corporation.fundingRound]; const funding = val * percShares * roundMultiplier; @@ -166,7 +166,7 @@ export function NetscriptCorporation(): InternalAPI { corporation.public ) return false; - const val = corporation.determineValuation(); + const val = corporation.valuation; const percShares = CorporationConstants.FundingRoundShares[corporation.fundingRound]; const roundMultiplier = CorporationConstants.FundingRoundMultiplier[corporation.fundingRound]; const funding = val * percShares * roundMultiplier; @@ -179,7 +179,7 @@ export function NetscriptCorporation(): InternalAPI { function goPublic(numShares: number): boolean { const corporation = getCorporation(); - const initialSharePrice = corporation.determineValuation() / corporation.totalShares; + const initialSharePrice = corporation.valuation / corporation.totalShares; if (isNaN(numShares)) throw new Error("Invalid value for number of issued shares"); if (numShares < 0) throw new Error("Invalid value for number of issued shares"); if (numShares > corporation.numShares) throw new Error("You don't have that many shares to issue!");