import { Box, Container, Paper, Table, TableBody, Tooltip } from "@mui/material"; import Button from "@mui/material/Button"; import Typography from "@mui/material/Typography"; import { uniqueId } from "lodash"; import React, { useEffect, useState } from "react"; import { Companies } from "../Company/Companies"; import { CONSTANTS } from "../Constants"; import { LocationName } from "../utils/enums"; import { Locations } from "../Locations/Locations"; import { Settings } from "../Settings/Settings"; import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; import { Player } from "@player"; import { Router } from "./GameRoot"; import { numeralWrapper } from "./numeralFormat"; import { Money } from "./React/Money"; import { MoneyRate } from "./React/MoneyRate"; import { ProgressBar } from "./React/Progress"; import { Reputation } from "./React/Reputation"; import { ReputationRate } from "./React/ReputationRate"; import { StatsRow } from "./React/StatsRow"; import { isCrimeWork } from "../Work/CrimeWork"; import { isClassWork } from "../Work/ClassWork"; import { WorkStats } from "../Work/WorkStats"; import { isCreateProgramWork } from "../Work/CreateProgramWork"; import { isGraftingWork } from "../Work/GraftingWork"; import { isFactionWork } from "../Work/FactionWork"; import { FactionWorkType } from "../utils/enums"; import { isCompanyWork } from "../Work/CompanyWork"; const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle; interface IWorkInfo { buttons: { cancel: () => void; unfocus?: () => void; }; title: string | React.ReactElement; description?: string | React.ReactElement; gains?: (string | React.ReactElement)[]; progress?: { elapsed?: number; remaining?: number; percentage?: number; }; stopText: string; stopTooltip?: string | React.ReactElement; } function ExpRows(rate: WorkStats): React.ReactElement[] { return [ rate.hackExp > 0 ? ( ) : ( <> ), rate.strExp > 0 ? ( ) : ( <> ), rate.defExp > 0 ? ( ) : ( <> ), rate.dexExp > 0 ? ( ) : ( <> ), rate.agiExp > 0 ? ( ) : ( <> ), rate.chaExp > 0 ? ( ) : ( <> ), ]; } /* Because crime exp is given all at once at the end, we don't care about the cycles per second. */ function CrimeExpRows(rate: WorkStats): React.ReactElement[] { return [ rate.hackExp > 0 ? ( ) : ( <> ), rate.strExp > 0 ? ( ) : ( <> ), rate.defExp > 0 ? ( ) : ( <> ), rate.dexExp > 0 ? ( ) : ( <> ), rate.agiExp > 0 ? ( ) : ( <> ), rate.chaExp > 0 ? ( ) : ( <> ), ]; } export function WorkInProgressRoot(): React.ReactElement { const setRerender = useState(false)[1]; function rerender(): void { setRerender((old) => !old); } useEffect(() => { const id = setInterval(rerender, CONSTANTS.MilliPerCycle); return () => clearInterval(id); }, []); let workInfo: IWorkInfo = { buttons: { cancel: () => undefined, }, title: "", stopText: "", }; if (Player.currentWork === null) { setTimeout(() => Router.toTerminal()); return <>; } if (isCrimeWork(Player.currentWork)) { const crime = Player.currentWork.getCrime(); const completion = (Player.currentWork.unitCompleted / crime.time) * 100; const gains = Player.currentWork.earnings(); const successChance = crime.successRate(Player); workInfo = { buttons: { cancel: () => { Router.toLocation(Locations[LocationName.Slums]); Player.finishWork(true); }, unfocus: () => { Router.toCity(); Player.stopFocusing(); }, }, title: `You are attempting ${crime.workName}`, gains: [ Success chance: {numeralWrapper.formatPercentage(successChance)}, Gains (on success), , ...CrimeExpRows(gains), ], progress: { remaining: crime.time - Player.currentWork.unitCompleted, percentage: completion, }, stopText: "Stop committing crime", }; } if (isClassWork(Player.currentWork)) { const classWork = Player.currentWork; function cancel(): void { Player.finishWork(true); Router.toCity(); } function unfocus(): void { Router.toCity(); Player.stopFocusing(); } let stopText = ""; if (classWork.isGym()) { stopText = "Stop training at gym"; } else { stopText = "Stop taking course"; } const rates = classWork.calculateRates(); workInfo = { buttons: { cancel: cancel, unfocus: unfocus, }, title: ( <> You are currently {classWork.getClass().youAreCurrently} ), gains: [ () , ...ExpRows(rates), ], progress: { elapsed: classWork.cyclesWorked * CONSTANTS._idleSpeed, }, stopText: stopText, }; } if (isCreateProgramWork(Player.currentWork)) { const create = Player.currentWork; function cancel(): void { Player.finishWork(true); Router.toTerminal(); } function unfocus(): void { Router.toTerminal(); Player.stopFocusing(); } const completion = (create.unitCompleted / create.unitNeeded()) * 100; workInfo = { buttons: { cancel: cancel, unfocus: unfocus, }, title: ( <> You are currently working on coding {create.programName} ), progress: { elapsed: create.cyclesWorked * CONSTANTS._idleSpeed, percentage: completion, }, stopText: "Stop creating program", stopTooltip: "Your work will be saved and you can return to complete the program later.", }; } if (isGraftingWork(Player.currentWork)) { const graft = Player.currentWork; function cancel(): void { Player.finishWork(true); Router.toTerminal(); } function unfocus(): void { Router.toTerminal(); Player.stopFocusing(); } workInfo = { buttons: { cancel: cancel, unfocus: unfocus, }, title: ( <> You are currently working on grafting {graft.augmentation} ), progress: { elapsed: graft.cyclesWorked * CONSTANTS._idleSpeed, percentage: (graft.unitCompleted / graft.unitNeeded()) * 100, }, stopText: "Stop grafting", stopTooltip: ( <> If you cancel, your work will not be saved, and the money you spent will not be returned ), }; } if (isFactionWork(Player.currentWork)) { const faction = Player.currentWork.getFaction(); if (!faction) { workInfo = { buttons: { cancel: () => Router.toFactions(), }, title: `You have not joined ${Player.currentWork.factionName || "(Faction not found)"} at this time,` + " please try again if you think this should have worked", stopText: "Back to Factions", }; } function cancel(): void { Router.toFaction(faction); Player.finishWork(true); } function unfocus(): void { Router.toFaction(faction); Player.stopFocusing(); } const description = { [FactionWorkType.hacking]: "carrying out hacking contracts", [FactionWorkType.field]: "carrying out field missions", [FactionWorkType.security]: "performing security detail", }; const exp = Player.currentWork.getExpRates(); workInfo = { buttons: { cancel: cancel, unfocus: unfocus, }, title: ( <> You are currently {description[Player.currentWork.factionWorkType]} for {faction.name} ), description: ( <> Current Faction Reputation: ( ) ), gains: ExpRows(exp), progress: { elapsed: Player.currentWork.cyclesWorked * CONSTANTS._idleSpeed, }, stopText: "Stop Faction work", }; } if (isCompanyWork(Player.currentWork)) { const comp = Companies[Player.currentWork.companyName]; if (comp) { workInfo = { buttons: { cancel: () => Router.toTerminal(), }, title: `You cannot work for ${Player.currentWork.companyName || "(Company not found)"} at this time,` + " please try again if you think this should have worked", stopText: "Back to Terminal", }; } const companyRep = comp.playerReputation; function cancel(): void { Player.finishWork(true); Router.toJob(Locations[comp.name]); } function unfocus(): void { Player.stopFocusing(); Router.toJob(Locations[comp.name]); } const position = Player.jobs[Player.currentWork.companyName]; const gains = Player.currentWork.getGainRates(); workInfo = { buttons: { cancel: cancel, unfocus: unfocus, }, title: ( <> You are currently working as a {position} at {Player.currentWork.companyName} ), description: ( <> Current Company Reputation: ), gains: [ , , ...ExpRows(gains), ], progress: { elapsed: Player.currentWork.cyclesWorked * CONSTANTS._idleSpeed, }, stopText: "Stop working", }; } if (workInfo.title === "") { return <>; } const tooltipInfo = typeof workInfo?.stopTooltip === "string" ? ( {workInfo.stopTooltip} ) : ( workInfo.stopTooltip || <> ); return ( {workInfo.title} {workInfo.description} {workInfo.gains && ( {workInfo.gains.map((row) => ( {row} ))}
)}
{workInfo.progress !== undefined && ( {workInfo.progress.elapsed !== undefined && ( {convertTimeMsToTimeElapsedString(workInfo.progress.elapsed)} elapsed )} {workInfo.progress.remaining !== undefined && ( {convertTimeMsToTimeElapsedString(workInfo.progress.remaining)} remaining )} {workInfo.progress.percentage !== undefined && ( {workInfo.progress.percentage.toFixed(2)}% done )} {workInfo.progress.percentage !== undefined && ( )} )} {workInfo.stopTooltip ? ( ) : ( )} {workInfo.buttons.unfocus && ( )}
); }