Files
bitburner-src/src/Corporation/ui/Overview.tsx
2022-04-01 21:55:23 +08:00

306 lines
12 KiB
TypeScript

// React Component for displaying Corporation Overview info
import React, { useState } from "react";
import { LevelableUpgrade } from "./LevelableUpgrade";
import { UnlockUpgrade } from "./UnlockUpgrade";
import { BribeFactionModal } from "./modals/BribeFactionModal";
import { SellSharesModal } from "./modals/SellSharesModal";
import { BuybackSharesModal } from "./modals/BuybackSharesModal";
import { IssueDividendsModal } from "./modals/IssueDividendsModal";
import { IssueNewSharesModal } from "./modals/IssueNewSharesModal";
import { FindInvestorsModal } from "./modals/FindInvestorsModal";
import { GoPublicModal } from "./modals/GoPublicModal";
import { Factions } from "../../Faction/Factions";
import { CorporationConstants } from "../data/Constants";
import { CorporationUnlockUpgrade, CorporationUnlockUpgrades } from "../data/CorporationUnlockUpgrades";
import { CorporationUpgrade, CorporationUpgrades } from "../data/CorporationUpgrades";
import { CONSTANTS } from "../../Constants";
import { numeralWrapper } from "../../ui/numeralFormat";
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
import { Money } from "../../ui/React/Money";
import { MoneyRate } from "../../ui/React/MoneyRate";
import { StatsTable } from "../../ui/React/StatsTable";
import { use } from "../../ui/Context";
import { useCorporation } from "./Context";
import Typography from "@mui/material/Typography";
import Tooltip from "@mui/material/Tooltip";
import Button from "@mui/material/Button";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Grid from "@mui/material/Grid";
interface IProps {
rerender: () => void;
}
export function Overview({ rerender }: IProps): React.ReactElement {
const player = use.Player();
const corp = useCorporation();
const profit: number = corp.revenue - corp.expenses;
const multRows: any[][] = [];
function appendMult(name: string, value: number): void {
if (value === 1) return;
multRows.push([name, numeralWrapper.format(value, "0.000")]);
}
appendMult("Production Multiplier: ", corp.getProductionMultiplier());
appendMult("Storage Multiplier: ", corp.getStorageMultiplier());
appendMult("Advertising Multiplier: ", corp.getAdvertisingMultiplier());
appendMult("Empl. Creativity Multiplier: ", corp.getEmployeeCreMultiplier());
appendMult("Empl. Charisma Multiplier: ", corp.getEmployeeChaMultiplier());
appendMult("Empl. Intelligence Multiplier: ", corp.getEmployeeIntMultiplier());
appendMult("Empl. Efficiency Multiplier: ", corp.getEmployeeEffMultiplier());
appendMult("Sales Multiplier: ", corp.getSalesMultiplier());
appendMult("Scientific Research Multiplier: ", corp.getScientificResearchMultiplier());
return (
<>
<StatsTable
rows={[
["Total Funds:", <Money money={corp.funds} />],
["Total Revenue:", <MoneyRate money={corp.revenue} />],
["Total Expenses:", <MoneyRate money={corp.expenses} />],
["Publicly Traded:", corp.public ? "Yes" : "No"],
["Owned Stock Shares:", numeralWrapper.format(corp.numShares, "0.000a")],
["Stock Price:", corp.public ? <Money money={corp.sharePrice} /> : "N/A"],
]}
/>
<br />
<Box display="flex">
<Tooltip
title={
<StatsTable
rows={[
["Outstanding Shares:", numeralWrapper.format(corp.issuedShares, "0.000a")],
[
"Private Shares:",
numeralWrapper.format(corp.totalShares - corp.issuedShares - corp.numShares, "0.000a"),
],
]}
/>
}
>
<Typography>Total Stock Shares: {numeralWrapper.format(corp.totalShares, "0.000a")}</Typography>
</Tooltip>
</Box>
<br />
<DividendsStats profit={profit} />
<br />
<StatsTable rows={multRows} />
<br />
<BonusTime />
<Box sx={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", width: "fit-content" }}>
<Tooltip
title={
<Typography>
Get a copy of and read 'The Complete Handbook for Creating a Successful Corporation.' This is a .lit file
that guides you through the beginning of setting up a Corporation and provides some tips/pointers for
helping you get started with managing it.
</Typography>
}
>
<Button onClick={() => corp.getStarterGuide(player)}>Getting Started Guide</Button>
</Tooltip>
{corp.public ? <PublicButtons rerender={rerender} /> : <PrivateButtons rerender={rerender} />}
<BribeButton />
</Box>
<br />
<Upgrades rerender={rerender} />
</>
);
}
interface IPrivateButtonsProps {
rerender: () => void;
}
// Render the buttons for when your Corporation is still private
function PrivateButtons({ rerender }: IPrivateButtonsProps): React.ReactElement {
const corp = useCorporation();
const [findInvestorsopen, setFindInvestorsopen] = useState(false);
const [goPublicopen, setGoPublicopen] = useState(false);
const fundingAvailable = corp.fundingRound < 4;
const findInvestorsTooltip = fundingAvailable
? "Search for private investors who will give you startup funding in exchange for equity (stock shares) in your company"
: "";
return (
<>
<Tooltip title={<Typography>{findInvestorsTooltip}</Typography>}>
<Button disabled={!fundingAvailable} onClick={() => setFindInvestorsopen(true)}>
Find Investors
</Button>
</Tooltip>
<Tooltip
title={
<Typography>
Become a publicly traded and owned entity. Going public involves issuing shares for an IPO. Once you are a
public company, your shares will be traded on the stock market.
</Typography>
}
>
<Button onClick={() => setGoPublicopen(true)}>Go Public</Button>
</Tooltip>
<FindInvestorsModal open={findInvestorsopen} onClose={() => setFindInvestorsopen(false)} rerender={rerender} />
<GoPublicModal open={goPublicopen} onClose={() => setGoPublicopen(false)} rerender={rerender} />
</>
);
}
interface IUpgradeProps {
rerender: () => void;
}
// Render the UI for Corporation upgrades
function Upgrades({ rerender }: IUpgradeProps): React.ReactElement {
const corp = useCorporation();
// Don't show upgrades
if (corp.divisions.length <= 0) {
return <Typography variant="h4">Upgrades are unlocked once you create an industry.</Typography>;
}
return (
<>
<Paper sx={{ p: 1, my: 1 }}>
<Typography variant="h4">Unlocks</Typography>
<Grid container>
{Object.values(CorporationUnlockUpgrades)
.filter((upgrade: CorporationUnlockUpgrade) => !corp.unlockUpgrades[upgrade[0]])
.map((upgrade: CorporationUnlockUpgrade) => (
<UnlockUpgrade rerender={rerender} upgradeData={upgrade} key={upgrade[0]} />
))}
</Grid>
</Paper>
<Paper sx={{ p: 1, my: 1 }}>
<Typography variant="h4">Upgrades</Typography>
<Grid container>
{corp.upgrades
.map((level: number, i: number) => CorporationUpgrades[i])
.map((upgrade: CorporationUpgrade) => (
<LevelableUpgrade rerender={rerender} upgrade={upgrade} key={upgrade[0]} />
))}
</Grid>
</Paper>
</>
);
}
interface IPublicButtonsProps {
rerender: () => void;
}
// Render the buttons for when your Corporation has gone public
function PublicButtons({ rerender }: IPublicButtonsProps): React.ReactElement {
const corp = useCorporation();
const [sellSharesOpen, setSellSharesOpen] = useState(false);
const [buybackSharesOpen, setBuybackSharesOpen] = useState(false);
const [issueNewSharesOpen, setIssueNewSharesOpen] = useState(false);
const [issueDividendsOpen, setIssueDividendsOpen] = useState(false);
const sellSharesOnCd = corp.shareSaleCooldown > 0;
const sellSharesTooltip = sellSharesOnCd
? "Cannot sell shares for " + corp.convertCooldownToString(corp.shareSaleCooldown)
: "Sell your shares in the company. The money earned from selling your " +
"shares goes into your personal account, not the Corporation's. " +
"This is one of the only ways to profit from your business venture.";
const issueNewSharesOnCd = corp.issueNewSharesCooldown > 0;
const issueNewSharesTooltip = issueNewSharesOnCd
? "Cannot issue new shares for " + corp.convertCooldownToString(corp.issueNewSharesCooldown)
: "Issue new equity shares to raise capital.";
return (
<>
<Tooltip title={<Typography>{sellSharesTooltip}</Typography>}>
<Button disabled={sellSharesOnCd} onClick={() => setSellSharesOpen(true)}>
Sell Shares
</Button>
</Tooltip>
<SellSharesModal open={sellSharesOpen} onClose={() => setSellSharesOpen(false)} rerender={rerender} />
<Tooltip title={<Typography>Buy back shares you that previously issued or sold at market price.</Typography>}>
<Button disabled={corp.issuedShares < 1} onClick={() => setBuybackSharesOpen(true)}>
Buyback shares
</Button>
</Tooltip>
<BuybackSharesModal open={buybackSharesOpen} onClose={() => setBuybackSharesOpen(false)} rerender={rerender} />
<Tooltip title={<Typography>{issueNewSharesTooltip}</Typography>}>
<Button disabled={issueNewSharesOnCd} onClick={() => setIssueNewSharesOpen(true)}>
Issue New Shares
</Button>
</Tooltip>
<IssueNewSharesModal open={issueNewSharesOpen} onClose={() => setIssueNewSharesOpen(false)} />
<Tooltip
title={<Typography>Manage the dividends that are paid out to shareholders (including yourself)</Typography>}
>
<Button onClick={() => setIssueDividendsOpen(true)}>Issue Dividends</Button>
</Tooltip>
<IssueDividendsModal open={issueDividendsOpen} onClose={() => setIssueDividendsOpen(false)} />
</>
);
}
function BribeButton(): React.ReactElement {
const player = use.Player();
const corp = useCorporation();
const [open, setOpen] = useState(false);
const canBribe =
corp.determineValuation() >= CorporationConstants.BribeThreshold &&
player.factions.filter((f) => Factions[f].getInfo().offersWork()).length > 0;
function openBribe(): void {
if (!canBribe) return;
setOpen(true);
}
return (
<>
<Tooltip
title={
canBribe
? "Use your Corporations power and influence to bribe Faction leaders in exchange for reputation"
: "Your Corporation is not powerful enough to bribe Faction leaders"
}
>
<Button disabled={!canBribe} onClick={openBribe}>
Bribe Factions
</Button>
</Tooltip>
<BribeFactionModal open={open} onClose={() => setOpen(false)} />
</>
);
}
interface IDividendsStatsProps {
profit: number;
}
function DividendsStats({ profit }: IDividendsStatsProps): React.ReactElement {
const corp = useCorporation();
if (corp.dividendPercentage <= 0 || profit <= 0) return <></>;
const totalDividends = (corp.dividendPercentage / 100) * profit;
const retainedEarnings = profit - totalDividends;
const dividendsPerShare = totalDividends / corp.totalShares;
return (
<StatsTable
rows={[
["Retained Profits (after dividends):", <MoneyRate money={retainedEarnings} />],
["Dividend Percentage:", numeralWrapper.format(corp.dividendPercentage / 100, "0%")],
["Dividends per share:", <MoneyRate money={dividendsPerShare} />],
["Your earnings as a shareholder:", <MoneyRate money={corp.getDividends()} />],
]}
/>
);
}
// Returns a string with general information about Corporation
function BonusTime(): React.ReactElement {
const corp = useCorporation();
const storedTime = corp.storedCycles * CONSTANTS.MilliPerCycle;
if (storedTime <= 15000) return <></>;
return (
<Typography>
Bonus time: {convertTimeMsToTimeElapsedString(storedTime)}
<br />
<br />
</Typography>
);
}