removing some of the classes

This commit is contained in:
Olivier Gagnon 2021-10-01 13:08:37 -04:00
parent 97c04a1037
commit 4e8bb96f3f
58 changed files with 457 additions and 374 deletions

@ -0,0 +1,33 @@
import React, { useState, useEffect } from "react";
import { Modal } from "../../ui/React/Modal";
import { use } from "../../ui/Context";
import { EventEmitter } from "../../utils/EventEmitter";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
export const BitFlumeEvent = new EventEmitter<[]>();
export function BitFlumeModal(): React.ReactElement {
const router = use.Router();
const [open, setOpen] = useState(false);
function flume(): void {
router.toBitVerse(true, false);
setOpen(false);
}
useEffect(() => BitFlumeEvent.subscribe(() => setOpen(true)), []);
return (
<Modal open={open} onClose={() => setOpen(false)}>
<Typography>
WARNING: USING THIS PROGRAM WILL CAUSE YOU TO LOSE ALL OF YOUR PROGRESS ON THE CURRENT BITNODE.
<br />
<br />
Do you want to travel to the BitNode Nexus? This allows you to reset the current BitNode and select a new one.
</Typography>
<br />
<br />
<Button onClick={flume}>Travel to the BitVerse</Button>
</Modal>
);
}

@ -1,30 +0,0 @@
import React from "react";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { IRouter } from "../../ui/Router";
import { removePopup } from "../../ui/React/createPopup";
interface IProps {
player: IPlayer;
router: IRouter;
popupId: string;
}
export function BitFlumePopup(props: IProps): React.ReactElement {
function flume(): void {
props.router.toBitVerse(true, false);
removePopup(props.popupId);
}
return (
<>
WARNING: USING THIS PROGRAM WILL CAUSE YOU TO LOSE ALL OF YOUR PROGRESS ON THE CURRENT BITNODE.
<br />
<br />
Do you want to travel to the BitNode Nexus? This allows you to reset the current BitNode and select a new one.
<br />
<br />
<button className="std-button" onClick={flume}>
Travel to the BitVerse
</button>
</>
);
}

@ -150,7 +150,7 @@ export function BitverseRoot(props: IProps): React.ReactElement {
return ( return (
// prettier-ignore // prettier-ignore
<div className="noselect"> <>
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> O </Typography> <Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> O </Typography>
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | O O | O O | </Typography> <Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | O O | O O | </Typography>
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> O | | / __| \ | | O </Typography> <Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> O | | / __| \ | | O </Typography>
@ -203,7 +203,7 @@ export function BitverseRoot(props: IProps): React.ReactElement {
"> ", "> ",
"> (Enter a new BitNode using the image above)", "> (Enter a new BitNode using the image above)",
]} /> ]} />
</div> </>
); );
return <></>; return <></>;

@ -307,9 +307,9 @@ export class Blackjack extends Game<Props, State> {
const dealerHandValues = this.getHandDisplayValues(dealerHand); const dealerHandValues = this.getHandDisplayValues(dealerHand);
return ( return (
<div> <>
{/* Wager input */} {/* Wager input */}
<div> <Box>
<TextField <TextField
value={betInput} value={betInput}
label={ label={
@ -336,32 +336,30 @@ export class Blackjack extends Game<Props, State> {
}} }}
/> />
<p> <Typography>
{"Total earnings this session: "} {"Total earnings this session: "}
<Money money={gains} /> <Money money={gains} />
</p> </Typography>
</div> </Box>
{/* Buttons */} {/* Buttons */}
{!gameInProgress ? ( {!gameInProgress ? (
<div>
<Button onClick={this.startOnClick} disabled={wagerInvalid || !this.canStartGame()}> <Button onClick={this.startOnClick} disabled={wagerInvalid || !this.canStartGame()}>
Start Start
</Button> </Button>
</div>
) : ( ) : (
<div> <>
<Button onClick={this.playerHit}>Hit</Button> <Button onClick={this.playerHit}>Hit</Button>
<Button color="secondary" onClick={this.playerStay}> <Button color="secondary" onClick={this.playerStay}>
Stay Stay
</Button> </Button>
</div> </>
)} )}
{/* Main game part. Displays both if the game is in progress OR if there's a result so you can see {/* Main game part. Displays both if the game is in progress OR if there's a result so you can see
* the cards that led to that result. */} * the cards that led to that result. */}
{(gameInProgress || result !== Result.Pending) && ( {(gameInProgress || result !== Result.Pending) && (
<div> <>
<Box display="flex"> <Box display="flex">
<Paper elevation={2}> <Paper elevation={2}>
<pre>Player</pre> <pre>Player</pre>
@ -396,28 +394,18 @@ export class Blackjack extends Game<Props, State> {
)} )}
</Paper> </Paper>
</Box> </Box>
</div> </>
)} )}
{/* Results from previous round */} {/* Results from previous round */}
{result !== Result.Pending && ( {result !== Result.Pending && (
<p> <Typography>
{result} {result}
{this.isPlayerWinResult(result) && ( {this.isPlayerWinResult(result) && <Money money={this.state.bet} />}
<> {result === Result.DealerWon && <Money money={this.state.bet} />}
{" You gained "} </Typography>
<Money money={this.state.bet} /> )}
</> </>
)}
{result === Result.DealerWon && (
<>
{" You lost "}
<Money money={this.state.bet} />
</>
)}
</p>
)}
</div>
); );
} }
} }

@ -1,8 +1,10 @@
import React, { FC } from "react"; import React, { FC } from "react";
import { Card, Suit } from "./Card"; import { Card, Suit } from "./Card";
import { Theme } from "@mui/material";
import makeStyles from "@mui/styles/makeStyles"; import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles"; import createStyles from "@mui/styles/createStyles";
import Typography from "@mui/material/Typography";
import Paper from "@mui/material/Paper";
type Props = { type Props = {
card: Card; card: Card;
@ -56,11 +58,11 @@ export const ReactCard: FC<Props> = ({ card, hidden }) => {
throw new Error(`MissingCaseException: ${card.suit}`); throw new Error(`MissingCaseException: ${card.suit}`);
} }
return ( return (
<div className={`${classes.card} ${card.isRedSuit() ? classes.red : classes.black}`}> <Paper className={`${classes.card} ${card.isRedSuit() ? classes.red : classes.black}`}>
<> <>
<div className={classes.value}>{hidden ? " - " : card.formatValue()}</div> <span className={classes.value}>{hidden ? " - " : card.formatValue()}</span>
<div>{hidden ? " - " : suit}</div> <span>{hidden ? " - " : suit}</span>
</> </>
</div> </Paper>
); );
}; };

@ -3,8 +3,7 @@ import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, SolverFunc
import { IMap } from "./types"; import { IMap } from "./types";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "./utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "./utils/JSONReviver";
import { createPopup, removePopup } from "./ui/React/createPopup"; import { CodingContractEvent } from "./ui/React/CodingContractModal";
import { CodingContractPopup } from "./ui/React/CodingContractPopup";
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */ /* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
@ -166,17 +165,11 @@ export class CodingContract {
* Creates a popup to prompt the player to solve the problem * Creates a popup to prompt the player to solve the problem
*/ */
async prompt(): Promise<CodingContractResult> { async prompt(): Promise<CodingContractResult> {
const popupId = `coding-contract-prompt-popup-${this.fn}`;
return new Promise<CodingContractResult>((resolve) => { return new Promise<CodingContractResult>((resolve) => {
createPopup( const props = {
popupId,
CodingContractPopup,
{
c: this, c: this,
popupId: popupId,
onClose: () => { onClose: () => {
resolve(CodingContractResult.Cancelled); resolve(CodingContractResult.Cancelled);
removePopup(popupId);
}, },
onAttempt: (val: string) => { onAttempt: (val: string) => {
if (this.isSolution(val)) { if (this.isSolution(val)) {
@ -184,11 +177,9 @@ export class CodingContract {
} else { } else {
resolve(CodingContractResult.Failure); resolve(CodingContractResult.Failure);
} }
removePopup(popupId);
}, },
}, };
() => resolve(CodingContractResult.Cancelled), CodingContractEvent.emit(props);
);
}); });
} }

@ -125,7 +125,7 @@ function Text(): React.ReactElement {
} }
return ( return (
<div> <>
<Typography> <Typography>
Industry: {division.type} (Corp Funds: <Money money={corp.funds.toNumber()} />) Industry: {division.type} (Corp Funds: <Money money={corp.funds.toNumber()} />)
</Typography> </Typography>
@ -218,7 +218,7 @@ function Text(): React.ReactElement {
Research Research
</Button> </Button>
</Box> </Box>
</div> </>
); );
} }

@ -56,18 +56,6 @@ function WarehouseRoot(props: IProps): React.ReactElement {
props.rerender(); props.rerender();
} }
const ratioLines = [];
for (const matName in division.reqMats) {
if (division.reqMats.hasOwnProperty(matName)) {
const text = [" *", division.reqMats[matName], matName].join(" ");
ratioLines.push(
<div key={matName}>
<p>{text}</p>
</div>,
);
}
}
// Current State: // Current State:
let stateText; let stateText;
switch (division.state) { switch (division.state) {

@ -50,7 +50,7 @@ export function ThrowPartyModal(props: IProps): React.ReactElement {
} }
function EffectText(): React.ReactElement { function EffectText(): React.ReactElement {
if (isNaN(cost) || cost < 0) return <p>Invalid value entered!</p>; if (isNaN(cost) || cost < 0) return <Typography>Invalid value entered!</Typography>;
return ( return (
<Typography> <Typography>
Throwing this party will cost a total of <Money money={totalCost} /> Throwing this party will cost a total of <Money money={totalCost} />

@ -48,7 +48,6 @@ export function General(props: IProps): React.ReactElement {
<h2>General</h2> <h2>General</h2>
</AccordionSummary> </AccordionSummary>
<AccordionDetails> <AccordionDetails>
<div>
<Button onClick={addMoney(1e6)}> <Button onClick={addMoney(1e6)}>
<pre> <pre>
+ <Money money={1e6} /> + <Money money={1e6} />
@ -75,13 +74,12 @@ export function General(props: IProps): React.ReactElement {
</pre> </pre>
</Button> </Button>
<Button onClick={upgradeRam}>+ RAM</Button> <Button onClick={upgradeRam}>+ RAM</Button>
</div> <br />
<div>
<Button onClick={quickB1tFlum3}>Quick b1t_flum3.exe</Button> <Button onClick={quickB1tFlum3}>Quick b1t_flum3.exe</Button>
<Button onClick={b1tflum3}>Run b1t_flum3.exe</Button> <Button onClick={b1tflum3}>Run b1t_flum3.exe</Button>
<Button onClick={quickHackW0r1dD43m0n}>Quick w0rld_d34m0n</Button> <Button onClick={quickHackW0r1dD43m0n}>Quick w0rld_d34m0n</Button>
<Button onClick={hackW0r1dD43m0n}>Hack w0rld_d34m0n</Button> <Button onClick={hackW0r1dD43m0n}>Hack w0rld_d34m0n</Button>
</div>
</AccordionDetails> </AccordionDetails>
</Accordion> </Accordion>
); );

@ -18,19 +18,13 @@ import {
import { SourceFileFlags } from "../SourceFile/SourceFileFlags"; import { SourceFileFlags } from "../SourceFile/SourceFileFlags";
import { dialogBoxCreate } from "../ui/React/DialogBox"; import { dialogBoxCreate } from "../ui/React/DialogBox";
import { createPopup } from "../ui/React/createPopup"; import { InvitationEvent } from "./ui/InvitationModal";
import { InvitationPopup } from "./ui/InvitationPopup";
export function inviteToFaction(faction: Faction): void { export function inviteToFaction(faction: Faction): void {
Player.factionInvitations.push(faction.name); Player.factionInvitations.push(faction.name);
faction.alreadyInvited = true; faction.alreadyInvited = true;
if (!Settings.SuppressFactionInvites) { if (!Settings.SuppressFactionInvites) {
const popupId = "faction-invitation"; InvitationEvent.emit(faction);
createPopup(popupId, InvitationPopup, {
player: Player,
faction: faction,
popupId: popupId,
});
} }
} }

@ -57,7 +57,7 @@ export function DonateOption(props: IProps): React.ReactElement {
props.faction.playerReputation += repGain; props.faction.playerReputation += repGain;
dialogBoxCreate( dialogBoxCreate(
<> <>
You just donated <Money money={amt} /> to {fac.name} to gain {Reputation(repGain)} reputation. You just donated <Money money={amt} /> to {fac.name} to gain <Reputation reputation={repGain} /> reputation.
</>, </>,
); );
props.rerender(); props.rerender();
@ -71,7 +71,7 @@ export function DonateOption(props: IProps): React.ReactElement {
} }
return ( return (
<Typography> <Typography>
This donation will result in {Reputation(repFromDonation(donateAmt, props.p))} reputation gain This donation will result in <Reputation reputation={repFromDonation(donateAmt, props.p)} /> reputation gain
</Typography> </Typography>
); );
} }
@ -81,7 +81,7 @@ export function DonateOption(props: IProps): React.ReactElement {
<Status /> <Status />
{props.disabled ? ( {props.disabled ? (
<Typography> <Typography>
Unlock donations at {Favor(props.favorToDonate)} favor with {props.faction.name} Unlock donations at <Favor favor={props.favorToDonate} /> favor with {props.faction.name}
</Typography> </Typography>
) : ( ) : (
<> <>

@ -54,7 +54,8 @@ export function Info(props: IProps): React.ReactElement {
title={ title={
<> <>
<Typography> <Typography>
You will have {Favor(props.faction.favor + favorGain)} faction favor after installing an Augmentation. You will have <Favor favor={props.faction.favor + favorGain} /> faction favor after installing an
Augmentation.
</Typography> </Typography>
<MathComponent tex={String.raw`\large{r = \text{total faction reputation}}`} /> <MathComponent tex={String.raw`\large{r = \text{total faction reputation}}`} />
<MathComponent <MathComponent
@ -63,7 +64,9 @@ export function Info(props: IProps): React.ReactElement {
</> </>
} }
> >
<Typography>Reputation: {Reputation(props.faction.playerReputation)}</Typography> <Typography>
Reputation: <Reputation reputation={props.faction.playerReputation} />
</Typography>
</Tooltip> </Tooltip>
</Box> </Box>
@ -83,7 +86,9 @@ export function Info(props: IProps): React.ReactElement {
</> </>
} }
> >
<Typography>Faction Favor: {Favor(props.faction.favor)}</Typography> <Typography>
Faction Favor: <Favor favor={props.faction.favor} />
</Typography>
</Tooltip> </Tooltip>
</Box> </Box>

@ -0,0 +1,40 @@
import React, { useState, useEffect } from "react";
import { joinFaction } from "../FactionHelpers";
import { Faction } from "../Faction";
import { Modal } from "../../ui/React/Modal";
import { use } from "../../ui/Context";
import { EventEmitter } from "../../utils/EventEmitter";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
export const InvitationEvent = new EventEmitter<[Faction]>();
export function InvitationModal(): React.ReactElement {
const [faction, setFaction] = useState<Faction | null>(null);
const player = use.Player();
function join(): void {
if (faction === null) return;
//Remove from invited factions
const i = player.factionInvitations.findIndex((facName) => facName === faction.name);
if (i === -1) {
console.error("Could not find faction in Player.factionInvitations");
}
joinFaction(faction);
setFaction(null);
}
useEffect(() => InvitationEvent.subscribe((faction) => setFaction(faction)), []);
return (
<Modal open={faction !== null} onClose={() => setFaction(null)}>
<Typography variant="h4">You have received a faction invitation.</Typography>
<Typography>
Would you like to join {(faction || { name: "" }).name}? <br />
<br />
Warning: Joining this faction may prevent you from joining other factions during this run!
</Typography>
<Button onClick={join}>Join!</Button>
<Button onClick={() => setFaction(null)}>Decide later</Button>
</Modal>
);
}

@ -1,40 +0,0 @@
import React from "react";
import { joinFaction } from "../../Faction/FactionHelpers";
import { Faction } from "../../Faction/Faction";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { removePopup } from "../../ui/React/createPopup";
interface IProps {
player: IPlayer;
faction: Faction;
popupId: string;
}
export function InvitationPopup(props: IProps): React.ReactElement {
function join(): void {
//Remove from invited factions
const i = props.player.factionInvitations.findIndex((facName) => facName === props.faction.name);
if (i === -1) {
console.error("Could not find faction in Player.factionInvitations");
}
joinFaction(props.faction);
removePopup(props.popupId);
}
return (
<>
<h1>You have received a faction invitation.</h1>
<p>
Would you like to join {props.faction.name}? <br />
<br />
Warning: Joining this faction may prevent you from joining other factions during this run!
</p>
<button className="std-button" onClick={join}>
Join!
</button>
<button className="std-button" onClick={() => removePopup(props.popupId)}>
Decide later
</button>
</>
);
}

@ -57,7 +57,7 @@ function Requirements(props: IReqProps): React.ReactElement {
</TableCell> </TableCell>
<TableCell key={2}> <TableCell key={2}>
<Typography color={props.hasRep ? "primary" : "error"}> <Typography color={props.hasRep ? "primary" : "error"}>
Requires {Reputation(props.rep)} faction reputation Requires <Reputation reputation={props.rep} /> faction reputation
</Typography> </Typography>
</TableCell> </TableCell>
</React.Fragment> </React.Fragment>

@ -66,7 +66,7 @@ export function GangStats(props: IProps): React.ReactElement {
</p> </p>
<br /> <br />
<p style={{ display: "inline-block" }}> <p style={{ display: "inline-block" }}>
Faction reputation: {Reputation(Factions[props.gang.facName].playerReputation)} Faction reputation: <Reputation reputation={Factions[props.gang.facName].playerReputation} />
</p> </p>
<br /> <br />
<BonusTime gang={props.gang} /> <BonusTime gang={props.gang} />

@ -183,7 +183,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
</TableCell> </TableCell>
<TableCell colSpan={2}> <TableCell colSpan={2}>
<Typography> <Typography>
{Hashes(node.totalHashesGenerated)} ({HashRate(node.hashRate)}) <Hashes hashes={node.totalHashesGenerated} /> (<HashRate hashes={node.hashRate} />)
</Typography> </Typography>
</TableCell> </TableCell>
</TableRow> </TableRow>
@ -192,7 +192,9 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
<Typography>Hash Capacity:</Typography> <Typography>Hash Capacity:</Typography>
</TableCell> </TableCell>
<TableCell colSpan={2}> <TableCell colSpan={2}>
<Typography>{Hashes(node.hashCapacity)}</Typography> <Typography>
<Hashes hashes={node.hashCapacity} />
</Typography>
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>

@ -60,7 +60,7 @@ export function HacknetUpgradeElem(props: IProps): React.ReactElement {
<CopyableText value={upg.name} /> <CopyableText value={upg.name} />
</Typography> </Typography>
<Typography> <Typography>
Cost: {Hashes(cost)}, Bought: {level} times Cost: <Hashes hashes={cost} />, Bought: {level} times
</Typography> </Typography>
<Typography>{upg.desc}</Typography> <Typography>{upg.desc}</Typography>

@ -6,8 +6,6 @@ import React, { useState, useEffect } from "react";
import { HashManager } from "../HashManager"; import { HashManager } from "../HashManager";
import { HashUpgrades } from "../HashUpgrades"; import { HashUpgrades } from "../HashUpgrades";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Hashes } from "../../ui/React/Hashes"; import { Hashes } from "../../ui/React/Hashes";
import { HacknetUpgradeElem } from "./HacknetUpgradeElem"; import { HacknetUpgradeElem } from "./HacknetUpgradeElem";
import { Modal } from "../../ui/React/Modal"; import { Modal } from "../../ui/React/Modal";
@ -40,7 +38,9 @@ export function HashUpgradeModal(props: IProps): React.ReactElement {
<Modal open={props.open} onClose={props.onClose}> <Modal open={props.open} onClose={props.onClose}>
<> <>
<Typography>Spend your hashes on a variety of different upgrades</Typography> <Typography>Spend your hashes on a variety of different upgrades</Typography>
<Typography>Hashes: {Hashes(player.hashManager.hashes)}</Typography> <Typography>
Hashes: <Hashes hashes={player.hashManager.hashes} />
</Typography>
{Object.keys(HashUpgrades).map((upgName) => { {Object.keys(HashUpgrades).map((upgName) => {
const upg = HashUpgrades[upgName]; const upg = HashUpgrades[upgName];
return ( return (

@ -9,14 +9,17 @@ import { PurchaseMultipliers } from "../data/Constants";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
interface IMultiplierProps { interface IMultiplierProps {
className: string; disabled: boolean;
key: string;
onClick: () => void; onClick: () => void;
text: string; text: string;
} }
function MultiplierButton(props: IMultiplierProps): React.ReactElement { function MultiplierButton(props: IMultiplierProps): React.ReactElement {
return <Button onClick={props.onClick}>{props.text}</Button>; return (
<Button disabled={props.disabled} onClick={props.onClick}>
{props.text}
</Button>
);
} }
interface IProps { interface IProps {
@ -35,13 +38,12 @@ export function MultiplierButtons(props: IProps): React.ReactElement {
for (let i = 0; i < mults.length; ++i) { for (let i = 0; i < mults.length; ++i) {
const mult = mults[i]; const mult = mults[i];
const btnProps = { const btnProps = {
className: props.purchaseMultiplier === PurchaseMultipliers[mult] ? "std-button-disabled" : "std-button", disabled: props.purchaseMultiplier === PurchaseMultipliers[mult],
key: mult,
onClick: onClicks[i], onClick: onClicks[i],
text: mult, text: mult,
}; };
buttons.push(<MultiplierButton {...btnProps} />); buttons.push(<MultiplierButton key={mult} {...btnProps} />);
} }
return <>{buttons}</>; return <>{buttons}</>;

@ -24,7 +24,7 @@ export function PlayerInfo(props: IProps): React.ReactElement {
let prod; let prod;
if (hasServers) { if (hasServers) {
prod = HashRate(props.totalProduction); prod = <HashRate hashes={props.totalProduction} />;
} else { } else {
prod = <MoneyRate money={props.totalProduction} />; prod = <MoneyRate money={props.totalProduction} />;
} }
@ -39,7 +39,8 @@ export function PlayerInfo(props: IProps): React.ReactElement {
{hasServers && ( {hasServers && (
<> <>
<Typography> <Typography>
Hashes: {Hashes(props.player.hashManager.hashes)} / {Hashes(props.player.hashManager.capacity)} Hashes: <Hashes hashes={props.player.hashManager.hashes} /> /{" "}
<Hashes hashes={props.player.hashManager.capacity} />
</Typography> </Typography>
</> </>
)} )}

@ -18,14 +18,10 @@ interface IProps {
export function PurchaseButton(props: IProps): React.ReactElement { export function PurchaseButton(props: IProps): React.ReactElement {
const cost = props.cost; const cost = props.cost;
let className = Player.canAfford(cost) ? "std-button" : "std-button-disabled";
let text; let text;
let style = {};
if (hasHacknetServers(Player)) { if (hasHacknetServers(Player)) {
if (hasMaxNumberHacknetServers(Player)) { if (hasMaxNumberHacknetServers(Player)) {
className = "std-button-disabled";
text = <>Hacknet Server limit reached</>; text = <>Hacknet Server limit reached</>;
style = { color: "red" };
} else { } else {
text = ( text = (
<> <>
@ -43,5 +39,9 @@ export function PurchaseButton(props: IProps): React.ReactElement {
); );
} }
return <Button onClick={props.onClick}>{text}</Button>; return (
<Button disabled={!Player.canAfford(cost)} onClick={props.onClick}>
{text}
</Button>
);
} }

@ -6,6 +6,7 @@ import { GameTimer } from "./GameTimer";
import { random } from "../utils"; import { random } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { BlinkingCursor } from "./BlinkingCursor"; import { BlinkingCursor } from "./BlinkingCursor";
import Typography from "@mui/material/Typography";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -46,17 +47,17 @@ export function BackwardGame(props: IMinigameProps): React.ReactElement {
<Grid container spacing={3}> <Grid container spacing={3}>
<GameTimer millis={timer} onExpire={props.onFailure} /> <GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}> <Grid item xs={12}>
<h1 className={"noselect"}>Type it backward</h1> <Typography variant="h4">Type it backward</Typography>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} /> <KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<p style={{ transform: "scaleX(-1)" }}>{answer}</p> <Typography style={{ transform: "scaleX(-1)" }}>{answer}</Typography>
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<p> <Typography>
{guess} {guess}
<BlinkingCursor /> <BlinkingCursor />
</p> </Typography>
</Grid> </Grid>
</Grid> </Grid>
); );

@ -6,6 +6,7 @@ import { GameTimer } from "./GameTimer";
import { random } from "../utils"; import { random } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { BlinkingCursor } from "./BlinkingCursor"; import { BlinkingCursor } from "./BlinkingCursor";
import Typography from "@mui/material/Typography";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -79,11 +80,11 @@ export function BracketGame(props: IMinigameProps): React.ReactElement {
<Grid container spacing={3}> <Grid container spacing={3}>
<GameTimer millis={timer} onExpire={props.onFailure} /> <GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}> <Grid item xs={12}>
<h1 className={"noselect"}>Close the brackets</h1> <Typography variant="h4">Close the brackets</Typography>
<p style={{ fontSize: "5em" }}> <Typography style={{ fontSize: "5em" }}>
{`${left}${right}`} {`${left}${right}`}
<BlinkingCursor /> <BlinkingCursor />
</p> </Typography>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} /> <KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid> </Grid>
</Grid> </Grid>

@ -4,6 +4,7 @@ import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler"; import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -51,13 +52,19 @@ export function BribeGame(props: IMinigameProps): React.ReactElement {
<Grid container spacing={3}> <Grid container spacing={3}>
<GameTimer millis={timer} onExpire={props.onFailure} /> <GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}> <Grid item xs={12}>
<h1>Say something nice about the guard.</h1> <Typography variant="h4">Say something nice about the guard.</Typography>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} /> <KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<h2 style={{ fontSize: "2em" }}></h2> <Typography variant="h5" color="primary">
<h2 style={{ fontSize: "2em" }}>{choices[index]}</h2>
<h2 style={{ fontSize: "2em" }}></h2> </Typography>
<Typography variant="h5" color="primary">
{choices[index]}
</Typography>
<Typography variant="h5" color="primary">
</Typography>
</Grid> </Grid>
</Grid> </Grid>
); );

@ -5,6 +5,7 @@ import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { random, getArrow } from "../utils"; import { random, getArrow } from "../utils";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -46,8 +47,8 @@ export function CheatCodeGame(props: IMinigameProps): React.ReactElement {
<Grid container spacing={3}> <Grid container spacing={3}>
<GameTimer millis={timer} onExpire={props.onFailure} /> <GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}> <Grid item xs={12}>
<h1 className={"noselect"}>Enter the Code!</h1> <Typography variant="h4">Enter the Code!</Typography>
<p style={{ fontSize: "5em" }}>{code[index]}</p> <Typography variant="h4">{code[index]}</Typography>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} /> <KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid> </Grid>
</Grid> </Grid>

@ -1,6 +1,7 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import Grid from "@mui/material/Grid"; import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
interface IProps { interface IProps {
onFinish: () => void; onFinish: () => void;
} }
@ -19,8 +20,8 @@ export function Countdown(props: IProps): React.ReactElement {
<> <>
<Grid container spacing={3}> <Grid container spacing={3}>
<Grid item xs={12}> <Grid item xs={12}>
<h1>Get Ready!</h1> <Typography variant="h4">Get Ready!</Typography>
<h1>{x}</h1> <Typography variant="h4">{x}</Typography>
</Grid> </Grid>
</Grid> </Grid>
</> </>

@ -5,6 +5,7 @@ import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { getArrow } from "../utils"; import { getArrow } from "../utils";
import Typography from "@mui/material/Typography";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -75,8 +76,8 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
<Grid container spacing={3}> <Grid container spacing={3}>
<GameTimer millis={timer} onExpire={props.onFailure} /> <GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}> <Grid item xs={12}>
<h1 className={"noselect"}>Match the symbols!</h1> <Typography variant="h4">Match the symbols!</Typography>
<h2 style={{ fontSize: fontSize }}> <Typography variant="h5" color="primary">
Targets:{" "} Targets:{" "}
{answer.map((a, i) => { {answer.map((a, i) => {
if (i == index) if (i == index)
@ -91,7 +92,7 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
</span> </span>
); );
})} })}
</h2> </Typography>
<br /> <br />
{grid.map((line, y) => ( {grid.map((line, y) => (
<div key={y}> <div key={y}>

@ -11,6 +11,7 @@ import { Cyberpunk2077Game } from "./Cyberpunk2077Game";
import { MinesweeperGame } from "./MinesweeperGame"; import { MinesweeperGame } from "./MinesweeperGame";
import { WireCuttingGame } from "./WireCuttingGame"; import { WireCuttingGame } from "./WireCuttingGame";
import { Victory } from "./Victory"; import { Victory } from "./Victory";
import Typography from "@mui/material/Typography";
interface IProps { interface IProps {
StartingDifficulty: number; StartingDifficulty: number;
@ -130,9 +131,9 @@ export function Game(props: IProps): React.ReactElement {
<> <>
<Grid container spacing={3}> <Grid container spacing={3}>
<Grid item xs={3}> <Grid item xs={3}>
<h3> <Typography>
Level: {level}&nbsp;/&nbsp;{props.MaxLevel} Level: {level}&nbsp;/&nbsp;{props.MaxLevel}
</h3> </Typography>
<Progress /> <Progress />
</Grid> </Grid>

@ -1,7 +1,8 @@
import React from "react"; import React from "react";
import { StdButton } from "../../ui/React/StdButton";
import { Location } from "../../Locations/Location"; import { Location } from "../../Locations/Location";
import Grid from "@mui/material/Grid"; import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
interface IProps { interface IProps {
Location: Location; Location: Location;
@ -52,37 +53,45 @@ export function Intro(props: IProps): React.ReactElement {
<> <>
<Grid container spacing={3}> <Grid container spacing={3}>
<Grid item xs={10}> <Grid item xs={10}>
<h1>Infiltrating {props.Location.name}</h1> <Typography variant="h4">Infiltrating {props.Location.name}</Typography>
</Grid> </Grid>
<Grid item xs={10}> <Grid item xs={10}>
<h2>Maximum level: {props.MaxLevel}</h2> <Typography variant="h5" color="primary">
Maximum level: {props.MaxLevel}
</Typography>
</Grid> </Grid>
<Grid item xs={10}> <Grid item xs={10}>
<pre>[{coloredArrow(props.Difficulty)}]</pre> <Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>[{coloredArrow(props.Difficulty)}]</Typography>
<pre>{` ^ ^ ^ ^`}</pre> <Typography
<pre>{` Trivial Normal Hard Impossible`}</pre> sx={{ lineHeight: "1em", whiteSpace: "pre" }}
>{` ^ ^ ^ ^`}</Typography>
<Typography
sx={{ lineHeight: "1em", whiteSpace: "pre" }}
>{` Trivial Normal Hard Impossible`}</Typography>
</Grid> </Grid>
<Grid item xs={10}> <Grid item xs={10}>
<p> <Typography>
Infiltration is a series of short minigames that get progressively harder. You take damage for failing them. Infiltration is a series of short minigames that get progressively harder. You take damage for failing them.
Reaching the maximum level rewards you with intel you can trade for money or reputation. Reaching the maximum level rewards you with intel you can trade for money or reputation.
</p> </Typography>
<br /> <br />
<p>The minigames you play are randomly selected. It might take you few tries to get used to them.</p> <Typography>
The minigames you play are randomly selected. It might take you few tries to get used to them.
</Typography>
<br /> <br />
<p>No game require use of the mouse.</p> <Typography>No game require use of the mouse.</Typography>
<br /> <br />
<p>Spacebar is the default action/confirm button.</p> <Typography>Spacebar is the default action/confirm button.</Typography>
<br /> <br />
<p>Everything that uses arrow can also use WASD</p> <Typography>Everything that uses arrow can also use WASD</Typography>
<br /> <br />
<p>Sometimes the rest of the keyboard is used.</p> <Typography>Sometimes the rest of the keyboard is used.</Typography>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<StdButton onClick={props.start} text={"Start"} /> <Button onClick={props.start}>Start</Button>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<StdButton onClick={props.cancel} text={"Cancel"} /> <Button onClick={props.cancel}>Cancel</Button>
</Grid> </Grid>
</Grid> </Grid>
</> </>

@ -5,6 +5,7 @@ import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import { getArrow } from "../utils"; import { getArrow } from "../utils";
import Typography from "@mui/material/Typography";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -81,7 +82,7 @@ export function MinesweeperGame(props: IMinigameProps): React.ReactElement {
<Grid container spacing={3}> <Grid container spacing={3}>
<GameTimer millis={timer} onExpire={props.onFailure} /> <GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}> <Grid item xs={12}>
<h1 className={"noselect"}>{memoryPhase ? "Remember all the mines!" : "Mark all the mines!"}</h1> <Typography variant="h4">{memoryPhase ? "Remember all the mines!" : "Mark all the mines!"}</Typography>
{minefield.map((line, y) => ( {minefield.map((line, y) => (
<div key={y}> <div key={y}>
<pre> <pre>

@ -4,6 +4,7 @@ import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler"; import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer"; import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty"; import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography";
interface Difficulty { interface Difficulty {
[key: string]: number; [key: string]: number;
@ -53,8 +54,8 @@ export function SlashGame(props: IMinigameProps): React.ReactElement {
<Grid container spacing={3}> <Grid container spacing={3}>
<GameTimer millis={5000} onExpire={props.onFailure} /> <GameTimer millis={5000} onExpire={props.onFailure} />
<Grid item xs={12}> <Grid item xs={12}>
<h1 className={"noselect"}>Slash when his guard is down!</h1> <Typography variant="h4">Slash when his guard is down!</Typography>
<p style={{ fontSize: "5em" }}>{guarding ? "!Guarding!" : "!ATTACKING!"}</p> <Typography variant="h4">{guarding ? "!Guarding!" : "!ATTACKING!"}</Typography>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} /> <KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid> </Grid>
</Grid> </Grid>

@ -1,11 +1,14 @@
import { Factions } from "../../Faction/Factions"; import { Factions } from "../../Faction/Factions";
import React, { useState } from "react"; import React, { useState } from "react";
import { StdButton } from "../../ui/React/StdButton";
import Grid from "@mui/material/Grid"; import Grid from "@mui/material/Grid";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { Reputation } from "../../ui/React/Reputation"; import { Reputation } from "../../ui/React/Reputation";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { use } from "../../ui/Context"; import { use } from "../../ui/Context";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import MenuItem from "@mui/material/MenuItem";
import Select, { SelectChangeEvent } from "@mui/material/Select";
interface IProps { interface IProps {
StartingDifficulty: number; StartingDifficulty: number;
@ -50,7 +53,7 @@ export function Victory(props: IProps): React.ReactElement {
quitInfiltration(); quitInfiltration();
} }
function changeDropdown(event: React.ChangeEvent<HTMLSelectElement>): void { function changeDropdown(event: SelectChangeEvent<string>): void {
setFaction(event.target.value); setFaction(event.target.value);
} }
@ -58,46 +61,36 @@ export function Victory(props: IProps): React.ReactElement {
<> <>
<Grid container spacing={3}> <Grid container spacing={3}>
<Grid item xs={10}> <Grid item xs={10}>
<h1>Infiltration successful!</h1> <Typography variant="h4">Infiltration successful!</Typography>
</Grid> </Grid>
<Grid item xs={10}> <Grid item xs={10}>
<h2>You can trade the confidential information you found for money or reputation.</h2> <Typography variant="h5" color="primary">
<select className={"dropdown"} onChange={changeDropdown}> You can trade the confidential information you found for money or reputation.
<option key={"none"} value={"none"}> </Typography>
<Select value={faction} onChange={changeDropdown}>
<MenuItem key={"none"} value={"none"}>
{"none"} {"none"}
</option> </MenuItem>
{player.factions {player.factions
.filter((f) => Factions[f].getInfo().offersWork()) .filter((f) => Factions[f].getInfo().offersWork())
.map((f) => ( .map((f) => (
<option key={f} value={f}> <MenuItem key={f} value={f}>
{f} {f}
</option> </MenuItem>
))} ))}
</select> </Select>
<StdButton <Button onClick={trade}>
onClick={trade} Trade for <Reputation reputation={repGain} /> reputation
text={ </Button>
<>
{"Trade for "}
{Reputation(repGain)}
{" reputation"}
</>
}
/>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<StdButton <Button onClick={sell}>
onClick={sell} Sell for&nbsp;
text={
<>
{"Sell for "}
<Money money={moneyGain} /> <Money money={moneyGain} />
</> </Button>
}
/>
</Grid> </Grid>
<Grid item xs={3}> <Grid item xs={3}>
<StdButton onClick={quitInfiltration} text={"Quit"} /> <Button onClick={quitInfiltration}>Quit</Button>
</Grid> </Grid>
</Grid> </Grid>
</> </>

@ -21,7 +21,6 @@ import * as posNames from "../../Company/data/companypositionnames";
import { Reputation } from "../../ui/React/Reputation"; import { Reputation } from "../../ui/React/Reputation";
import { Favor } from "../../ui/React/Favor"; import { Favor } from "../../ui/React/Favor";
import { createPopup } from "../../ui/React/createPopup";
import { use } from "../../ui/Context"; import { use } from "../../ui/Context";
import { QuitJobModal } from "../../Company/ui/QuitJobModal"; import { QuitJobModal } from "../../Company/ui/QuitJobModal";
@ -184,21 +183,23 @@ export function CompanyLocation(props: IProps): React.ReactElement {
const favorGain = company.getFavorGain(); const favorGain = company.getFavorGain();
return ( return (
<div> <>
{isEmployedHere && ( {isEmployedHere && (
<div> <>
<Typography>Job Title: {jobTitle}</Typography> <Typography>Job Title: {jobTitle}</Typography>
<Typography>-------------------------</Typography> <Typography>-------------------------</Typography>
<Box display="flex"> <Box display="flex">
<Tooltip <Tooltip
title={ title={
<> <>
You will have {Favor(company.favor + favorGain[0])} company favor upon resetting after installing You will have <Favor favor={company.favor + favorGain[0]} /> company favor upon resetting after
Augmentations installing Augmentations
</> </>
} }
> >
<Typography>Company reputation: {Reputation(company.playerReputation)}</Typography> <Typography>
Company reputation: <Reputation reputation={company.playerReputation} />
</Typography>
</Tooltip> </Tooltip>
</Box> </Box>
<Typography>-------------------------</Typography> <Typography>-------------------------</Typography>
@ -212,7 +213,9 @@ export function CompanyLocation(props: IProps): React.ReactElement {
</> </>
} }
> >
<Typography>Company Favor: {Favor(company.favor)}</Typography> <Typography>
Company Favor: <Favor favor={company.favor} />
</Typography>
</Tooltip> </Tooltip>
</Box> </Box>
<Typography>-------------------------</Typography> <Typography>-------------------------</Typography>
@ -227,8 +230,9 @@ export function CompanyLocation(props: IProps): React.ReactElement {
open={quitOpen} open={quitOpen}
onClose={() => setQuitOpen(false)} onClose={() => setQuitOpen(false)}
/> />
</div> </>
)} )}
<br />
{company.hasAgentPositions() && ( {company.hasAgentPositions() && (
<ApplyToJobButton <ApplyToJobButton
company={company} company={company}
@ -318,6 +322,6 @@ export function CompanyLocation(props: IProps): React.ReactElement {
/> />
)} )}
{location.infiltrationData != null && <Button onClick={startInfiltration}>Infiltrate Company</Button>} {location.infiltrationData != null && <Button onClick={startInfiltration}>Infiltrate Company</Button>}
</div> </>
); );
} }

@ -113,7 +113,7 @@ export function SlumsLocation(): React.ReactElement {
const heistChance = Crimes.Heist.successRate(player); const heistChance = Crimes.Heist.successRate(player);
return ( return (
<div> <>
<Tooltip title={<>Attempt to shoplift from a low-end retailer</>}> <Tooltip title={<>Attempt to shoplift from a low-end retailer</>}>
<Button onClick={shoplift}> <Button onClick={shoplift}>
Shoplift ({numeralWrapper.formatPercentage(shopliftChance)} chance of success) Shoplift ({numeralWrapper.formatPercentage(shopliftChance)} chance of success)
@ -180,6 +180,6 @@ export function SlumsLocation(): React.ReactElement {
<Button onClick={heist}>Heist ({numeralWrapper.formatPercentage(heistChance)} chance of success)</Button> <Button onClick={heist}>Heist ({numeralWrapper.formatPercentage(heistChance)} chance of success)</Button>
</Tooltip> </Tooltip>
<br /> <br />
</div> </>
); );
} }

@ -67,7 +67,7 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
} }
return ( return (
<div> <>
{purchaseServerButtons} {purchaseServerButtons}
<br /> <br />
<Typography> <Typography>
@ -79,6 +79,6 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
<RamButton p={player} rerender={rerender} /> <RamButton p={player} rerender={rerender} />
<br /> <br />
<CoresButton p={player} rerender={rerender} /> <CoresButton p={player} rerender={rerender} />
</div> </>
); );
} }

@ -76,7 +76,7 @@ export function TravelAgencyRoot(props: IProps): React.ReactElement {
<Money money={CONSTANTS.TravelCost} player={props.p} />. <Money money={CONSTANTS.TravelCost} player={props.p} />.
</Typography> </Typography>
{Settings.DisableASCIIArt ? ( {Settings.DisableASCIIArt ? (
<div> <>
{Object.values(CityName) {Object.values(CityName)
.filter((city: string) => city != props.p.city) .filter((city: string) => city != props.p.city)
.map((city: string) => { .map((city: string) => {
@ -91,7 +91,7 @@ export function TravelAgencyRoot(props: IProps): React.ReactElement {
</React.Fragment> </React.Fragment>
); );
})} })}
</div> </>
) : ( ) : (
<WorldMap currentCity={props.p.city} onTravel={(city: CityName) => startTravel(city)} /> <WorldMap currentCity={props.p.city} onTravel={(city: CityName) => startTravel(city)} />
)} )}

@ -626,7 +626,7 @@ export function finishWork(this: IPlayer, cancelled: boolean, sing = false): str
You earned a total of: <br /> You earned a total of: <br />
<Money money={this.workMoneyGained} /> <Money money={this.workMoneyGained} />
<br /> <br />
{Reputation(this.workRepGained)} reputation for the company <br /> <Reputation reputation={this.workRepGained} /> reputation for the company <br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br /> {numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br /> {numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />
@ -747,7 +747,7 @@ export function finishWorkPartTime(this: IPlayer, sing = false): string {
You earned a total of: <br /> You earned a total of: <br />
<Money money={this.workMoneyGained} /> <Money money={this.workMoneyGained} />
<br /> <br />
{Reputation(this.workRepGained)} reputation for the company <br /> <Reputation reputation={this.workRepGained} /> reputation for the company <br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br /> {numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br /> {numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />
@ -919,7 +919,7 @@ export function finishFactionWork(this: IPlayer, cancelled: boolean, sing = fals
You earned a total of: <br /> You earned a total of: <br />
<Money money={this.workMoneyGained} /> <Money money={this.workMoneyGained} />
<br /> <br />
{Reputation(this.workRepGained)} reputation for the faction <br /> <Reputation reputation={this.workRepGained} /> reputation for the faction <br />
{numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br /> {numeralWrapper.formatExp(this.workHackExpGained)} hacking exp <br />
{numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br /> {numeralWrapper.formatExp(this.workStrExpGained)} strength exp <br />
{numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br /> {numeralWrapper.formatExp(this.workDefExpGained)} defense exp <br />

@ -161,7 +161,7 @@ export function SleeveElem(props: IProps): React.ReactElement {
]; ];
if (props.sleeve.currentTask === SleeveTaskType.Company || props.sleeve.currentTask === SleeveTaskType.Faction) { if (props.sleeve.currentTask === SleeveTaskType.Company || props.sleeve.currentTask === SleeveTaskType.Faction) {
const repGain: number = props.sleeve.getRepGain(player); const repGain: number = props.sleeve.getRepGain(player);
data.push([`Reputation:`, ReputationRate(5 * repGain)]); data.push([`Reputation:`, <ReputationRate reputation={5 * repGain} />]);
} }
} }

@ -10,9 +10,7 @@ import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFuncti
import { getServer } from "../../Server/ServerHelpers"; import { getServer } from "../../Server/ServerHelpers";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { createPopup } from "../../ui/React/createPopup"; import { BitFlumeEvent } from "../../BitNode/ui/BitFlumeModal";
import { BitFlumePopup } from "../../BitNode/ui/BitFlumePopup";
import { calculateHackingTime, calculateGrowTime, calculateWeakenTime } from "../../Hacking"; import { calculateHackingTime, calculateGrowTime, calculateWeakenTime } from "../../Hacking";
function requireHackingLevel(lvl: number) { function requireHackingLevel(lvl: number) {
@ -286,12 +284,7 @@ export const programsMetadata: IProgramCreationParams[] = [
time: CONSTANTS.MillisecondsPerFiveMinutes / 20, time: CONSTANTS.MillisecondsPerFiveMinutes / 20,
}, },
run: (router: IRouter, terminal: ITerminal, player: IPlayer): void => { run: (router: IRouter, terminal: ITerminal, player: IPlayer): void => {
const popupId = "bitflume-popup"; BitFlumeEvent.emit();
createPopup(popupId, BitFlumePopup, {
player: player,
router: router,
popupId: popupId,
});
}, },
}, },
{ {

@ -307,7 +307,7 @@ export function Root(props: IProps): React.ReactElement {
<Editor <Editor
beforeMount={beforeMount} beforeMount={beforeMount}
onMount={onMount} onMount={onMount}
loading={<p>Loading script editor!</p>} loading={<Typography>Loading script editor!</Typography>}
height="90%" height="90%"
defaultLanguage="javascript" defaultLanguage="javascript"
defaultValue={code} defaultValue={code}

@ -40,7 +40,7 @@ function DisplayModeButton(props: IProps): React.ReactElement {
export function StockTickersConfig(props: IProps): React.ReactElement { export function StockTickersConfig(props: IProps): React.ReactElement {
return ( return (
<div> <>
<DisplayModeButton {...props} /> <DisplayModeButton {...props} />
<br /> <br />
<TextField <TextField
@ -49,6 +49,6 @@ export function StockTickersConfig(props: IProps): React.ReactElement {
placeholder="Filter Stocks by symbol (comma-separated list)" placeholder="Filter Stocks by symbol (comma-separated list)"
type="text" type="text"
/> />
</div> </>
); );
} }

@ -12,6 +12,9 @@ import { IRouter } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { TerminalInput } from "./TerminalInput"; import { TerminalInput } from "./TerminalInput";
import { TerminalEvents, TerminalClearEvents } from "../TerminalEvents"; import { TerminalEvents, TerminalClearEvents } from "../TerminalEvents";
import { BitFlumeModal } from "../../BitNode/ui/BitFlumeModal";
import { CodingContractModal } from "../../ui/React/CodingContractModal";
import _ from "lodash"; import _ from "lodash";
interface IActionTimerProps { interface IActionTimerProps {
@ -118,6 +121,8 @@ export function TerminalRoot({ terminal, router, player }: IProps): React.ReactE
<Box position="sticky" bottom={0} width="100%" px={0}> <Box position="sticky" bottom={0} width="100%" px={0}>
<TerminalInput player={player} router={router} terminal={terminal} /> <TerminalInput player={player} router={router} terminal={terminal} />
</Box> </Box>
<BitFlumeModal />
<CodingContractModal />
</> </>
); );
} }

@ -334,7 +334,9 @@ const Engine: {
// Hacknet Nodes offline progress // Hacknet Nodes offline progress
const offlineProductionFromHacknetNodes = processHacknetEarnings(Player, numCyclesOffline); const offlineProductionFromHacknetNodes = processHacknetEarnings(Player, numCyclesOffline);
const hacknetProdInfo = hasHacknetServers(Player) ? ( const hacknetProdInfo = hasHacknetServers(Player) ? (
<>{Hashes(offlineProductionFromHacknetNodes)} hashes</> <>
<Hashes hashes={offlineProductionFromHacknetNodes} /> hashes
</>
) : ( ) : (
<Money money={offlineProductionFromHacknetNodes} /> <Money money={offlineProductionFromHacknetNodes} />
); );
@ -405,7 +407,7 @@ const Engine: {
<> <>
Offline for {timeOfflineString}. While you were offline, your scripts generated{" "} Offline for {timeOfflineString}. While you were offline, your scripts generated{" "}
<Money money={offlineHackingIncome} />, your Hacknet Nodes generated {hacknetProdInfo} and you gained{" "} <Money money={offlineHackingIncome} />, your Hacknet Nodes generated {hacknetProdInfo} and you gained{" "}
{Reputation(offlineReputation)} divided amongst your factions. <Reputation reputation={offlineReputation} /> reputation divided amongst your factions.
</>, </>,
), ),
250, 250,

@ -69,6 +69,7 @@ import { Unclickable } from "../Exploits/Unclickable";
import { Snackbar } from "./React/Snackbar"; import { Snackbar } from "./React/Snackbar";
import { LogBoxManager } from "./React/LogBoxManager"; import { LogBoxManager } from "./React/LogBoxManager";
import { AlertManager } from "./React/AlertManager"; import { AlertManager } from "./React/AlertManager";
import { InvitationModal } from "../Faction/ui/InvitationModal";
import { enterBitNode } from "../RedPill"; import { enterBitNode } from "../RedPill";
import { Context } from "./Context"; import { Context } from "./Context";
@ -398,6 +399,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
<Snackbar /> <Snackbar />
<LogBoxManager /> <LogBoxManager />
<AlertManager /> <AlertManager />
<InvitationModal />
</Context.Router.Provider> </Context.Router.Provider>
</Context.Player.Provider> </Context.Player.Provider>
); );

@ -1,9 +1,17 @@
import * as React from "react"; import * as React from "react";
import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
aug: {
color: theme.colors.combat,
},
}),
);
export function Augmentation({ name }: { name: string }): JSX.Element { export function Augmentation({ name }: { name: string }): JSX.Element {
return ( const classes = useStyles();
<span className={"samefont"} style={{ color: "white" }}> return <span className={classes.aug}>{name}</span>;
{name}
</span>
);
} }

@ -60,7 +60,9 @@ function Work(): React.ReactElement {
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell component="th" scope="row" colSpan={2} classes={{ root: classes.cellNone }}> <TableCell component="th" scope="row" colSpan={2} classes={{ root: classes.cellNone }}>
<Typography>+{Reputation(player.workRepGained)} rep</Typography> <Typography>
+<Reputation reputation={player.workRepGained} /> rep
</Typography>
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>

@ -24,12 +24,12 @@ export function CinematicText(props: IProps): React.ReactElement {
} }
return ( return (
<div> <>
{props.lines.slice(0, i).map((line, i) => ( {props.lines.slice(0, i).map((line, i) => (
<Typography key={i}>{line}</Typography> <Typography key={i}>{line}</Typography>
))} ))}
{props.lines.length > i && <CinematicLine key={i} text={props.lines[i]} onDone={advance} />} {props.lines.length > i && <CinematicLine key={i} text={props.lines[i]} onDone={advance} />}
{!props.auto && props.onDone && done && <Button onClick={props.onDone}>Continue ...</Button>} {!props.auto && props.onDone && done && <Button onClick={props.onDone}>Continue ...</Button>}
</div> </>
); );
} }

@ -1,24 +1,37 @@
import React, { useState } from "react"; import React, { useState, useEffect } from "react";
import { KEY } from "../../utils/helpers/keyCodes"; import { KEY } from "../../utils/helpers/keyCodes";
import { CodingContract, CodingContractType, CodingContractTypes } from "../../CodingContracts"; import { CodingContract, CodingContractType, CodingContractTypes } from "../../CodingContracts";
import { ClickableTag, CopyableText } from "./CopyableText"; import { ClickableTag, CopyableText } from "./CopyableText";
import { Modal } from "./Modal";
import { EventEmitter } from "../../utils/EventEmitter";
import Typography from "@mui/material/Typography";
import TextField from "@mui/material/TextField";
import Button from "@mui/material/Button";
type IProps = { interface IProps {
c: CodingContract; c: CodingContract;
popupId: string;
onClose: () => void; onClose: () => void;
onAttempt: (answer: string) => void; onAttempt: (answer: string) => void;
}; }
export function CodingContractPopup(props: IProps): React.ReactElement { export const CodingContractEvent = new EventEmitter<[IProps]>();
export function CodingContractModal(): React.ReactElement {
const [props, setProps] = useState<IProps | null>(null);
const [answer, setAnswer] = useState(""); const [answer, setAnswer] = useState("");
useEffect(() => {
CodingContractEvent.subscribe((props) => setProps(props));
});
if (props === null) return <></>;
function onChange(event: React.ChangeEvent<HTMLInputElement>): void { function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
setAnswer(event.target.value); setAnswer(event.target.value);
} }
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void { function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
if (props === null) return;
// React just won't cooperate on this one. // React just won't cooperate on this one.
// "React.KeyboardEvent<HTMLInputElement>" seems like the right type but // "React.KeyboardEvent<HTMLInputElement>" seems like the right type but
// whatever ... // whatever ...
@ -30,34 +43,47 @@ export function CodingContractPopup(props: IProps): React.ReactElement {
} }
} }
function close(): void {
if (props === null) return;
props.onClose();
setProps(null);
}
const contractType: CodingContractType = CodingContractTypes[props.c.type]; const contractType: CodingContractType = CodingContractTypes[props.c.type];
const description = []; const description = [];
for (const [i, value] of contractType.desc(props.c.data).split("\n").entries()) for (const [i, value] of contractType.desc(props.c.data).split("\n").entries())
description.push(<span key={i} dangerouslySetInnerHTML={{ __html: value + "<br />" }}></span>); description.push(<span key={i} dangerouslySetInnerHTML={{ __html: value + "<br />" }}></span>);
return ( return (
<div> <Modal open={props !== null} onClose={close}>
<CopyableText value={props.c.type} tag={ClickableTag.Tag_h1} /> <Typography variant="h4">
<br /> <CopyableText value={props.c.type} />
<br /> </Typography>
<p> <Typography>
You are attempting to solve a Coding Contract. You have {props.c.getMaxNumTries() - props.c.tries} tries You are attempting to solve a Coding Contract. You have {props.c.getMaxNumTries() - props.c.tries} tries
remaining, after which the contract will self-destruct. remaining, after which the contract will self-destruct.
</p> </Typography>
<br /> <br />
<p>{description}</p> <Typography>{description}</Typography>
<br /> <br />
<input <TextField
className="text-input" autoFocus
style={{ width: "50%", marginTop: "8px" }}
autoFocus={true}
placeholder="Enter Solution here" placeholder="Enter Solution here"
value={answer} value={answer}
onChange={onChange} onChange={onChange}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
/> InputProps={{
<button className={"std-button"} onClick={() => props.onAttempt(answer)}> endAdornment: (
<Button
onClick={() => {
props.onAttempt(answer);
close();
}}
>
Solve Solve
</button> </Button>
</div> ),
}}
/>
</Modal>
); );
} }

@ -1,10 +1,18 @@
import * as React from "react"; import * as React from "react";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles";
export function Favor(favor: number | string): JSX.Element { const useStyles = makeStyles((theme: Theme) =>
return ( createStyles({
<span className={"light-yellow samefont"}> favor: {
{typeof favor === "number" ? numeralWrapper.formatFavor(favor) : favor} color: theme.colors.rep,
</span> },
}),
); );
export function Favor({ favor }: { favor: number | string }): React.ReactElement {
const classes = useStyles();
return <span className={classes.favor}>{typeof favor === "number" ? numeralWrapper.formatFavor(favor) : favor}</span>;
} }

@ -1,6 +1,7 @@
import React from "react";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { Hashes } from "../../ui/React/Hashes"; import { Hashes } from "../../ui/React/Hashes";
export function HashRate(hashes: number): JSX.Element { export function HashRate({ hashes }: { hashes: number }): React.ReactElement {
return Hashes(`${numeralWrapper.formatHashes(hashes)} / sec`); return <Hashes hashes={`${numeralWrapper.formatHashes(hashes)} / sec`} />;
} }

@ -1,10 +1,20 @@
import * as React from "react"; import * as React from "react";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles";
export function Hashes(hashes: number | string): JSX.Element { const useStyles = makeStyles((theme: Theme) =>
createStyles({
money: {
color: theme.colors.money,
},
}),
);
export function Hashes({ hashes }: { hashes: number | string }): React.ReactElement {
const classes = useStyles();
return ( return (
<span className={"money-gold samefont"}> <span className={classes.money}>{typeof hashes === "number" ? numeralWrapper.formatHashes(hashes) : hashes}</span>
{typeof hashes === "number" ? numeralWrapper.formatHashes(hashes) : hashes}
</span>
); );
} }

@ -42,6 +42,8 @@ export const Modal = (props: IProps): React.ReactElement => {
<M <M
disableRestoreFocus disableRestoreFocus
disableScrollLock disableScrollLock
disableEnforceFocus
disableAutoFocus
open={props.open} open={props.open}
onClose={props.onClose} onClose={props.onClose}
closeAfterTransition closeAfterTransition

@ -1,19 +1,34 @@
import * as React from "react"; import * as React from "react";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles";
const useStyles = makeStyles((theme: Theme) =>
createStyles({
unbuyable: {
color: theme.palette.action.disabled,
},
money: {
color: theme.colors.money,
},
}),
);
interface IProps { interface IProps {
money: number | string; money: number | string;
player?: IPlayer; player?: IPlayer;
} }
export function Money(props: IProps): JSX.Element { export function Money(props: IProps): React.ReactElement {
const classes = useStyles();
if (props.player !== undefined) { if (props.player !== undefined) {
if (typeof props.money !== "number") throw new Error("if player if provided, money should be number, contact dev"); if (typeof props.money !== "number") throw new Error("if player if provided, money should be number, contact dev");
if (!props.player.canAfford(props.money)) if (!props.player.canAfford(props.money))
return <span className={"unbuyable samefont"}>{numeralWrapper.formatMoney(props.money)}</span>; return <span className={classes.unbuyable}>{numeralWrapper.formatMoney(props.money)}</span>;
} }
return ( return (
<span className={"money-gold samefont"}> <span className={classes.money}>
{typeof props.money === "number" ? numeralWrapper.formatMoney(props.money) : props.money} {typeof props.money === "number" ? numeralWrapper.formatMoney(props.money) : props.money}
</span> </span>
); );

@ -1,10 +1,22 @@
import * as React from "react"; import * as React from "react";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles";
import createStyles from "@mui/styles/createStyles";
export function Reputation(reputation: number | string): JSX.Element { const useStyles = makeStyles((theme: Theme) =>
createStyles({
reputation: {
color: theme.colors.rep,
},
}),
);
export function Reputation({ reputation }: { reputation: number | string }): React.ReactElement {
const classes = useStyles();
return ( return (
<span className={"reputation samefont"}> <span className={classes.reputation}>
{typeof reputation === "number" ? numeralWrapper.formatReputation(reputation) : reputation} {typeof reputation === "number" ? numeralWrapper.formatFavor(reputation) : reputation}
</span> </span>
); );
} }

@ -1,6 +1,7 @@
import React from "react";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { Reputation } from "../../ui/React/Reputation"; import { Reputation } from "../../ui/React/Reputation";
export function ReputationRate(reputation: number): JSX.Element { export function ReputationRate({ reputation }: { reputation: number }): React.ReactElement {
return Reputation(`${numeralWrapper.formatReputation(reputation)} / sec`); return <Reputation reputation={`${numeralWrapper.formatReputation(reputation)} / sec`} />;
} }

@ -49,7 +49,8 @@ export function WorkInProgressRoot(): React.ReactElement {
<Typography> <Typography>
You are currently {player.currentWorkFactionDescription} for your faction {faction.name} You are currently {player.currentWorkFactionDescription} for your faction {faction.name}
<br /> <br />
(Current Faction Reputation: {Reputation(faction.playerReputation)}). <br /> (Current Faction Reputation: <Reputation reputation={faction.playerReputation} />
). <br />
You have been doing this for {convertTimeMsToTimeElapsedString(player.timeWorked)} You have been doing this for {convertTimeMsToTimeElapsedString(player.timeWorked)}
<br /> <br />
<br /> <br />
@ -58,8 +59,8 @@ export function WorkInProgressRoot(): React.ReactElement {
<Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "} <Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "}
<br /> <br />
<br /> <br />
{Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation <Reputation reputation={player.workRepGained} /> (
for this faction <br /> <ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />) reputation for this faction <br />
<br /> <br />
{numeralWrapper.formatExp(player.workHackExpGained)} ( {numeralWrapper.formatExp(player.workHackExpGained)} (
{numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br /> {numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br />
@ -171,7 +172,7 @@ export function WorkInProgressRoot(): React.ReactElement {
<Grid item> <Grid item>
<Typography> <Typography>
You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "} You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "}
{Reputation(companyRep)})<br /> <Reputation reputation={companyRep} />)<br />
<br /> <br />
You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)} You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)}
<br /> <br />
@ -181,8 +182,8 @@ export function WorkInProgressRoot(): React.ReactElement {
<Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "} <Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "}
<br /> <br />
<br /> <br />
{Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation <Reputation reputation={player.workRepGained} /> (
for this company <br /> <ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />) reputation for this company <br />
<br /> <br />
{numeralWrapper.formatExp(player.workHackExpGained)} ( {numeralWrapper.formatExp(player.workHackExpGained)} (
{`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`} {`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}
@ -241,7 +242,7 @@ export function WorkInProgressRoot(): React.ReactElement {
<Grid item> <Grid item>
<Typography> <Typography>
You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "} You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "}
{Reputation(companyRep)})<br /> <Reputation reputation={companyRep} />)<br />
<br /> <br />
You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)} You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)}
<br /> <br />
@ -251,8 +252,8 @@ export function WorkInProgressRoot(): React.ReactElement {
<Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "} <Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "}
<br /> <br />
<br /> <br />
{Reputation(player.workRepGained)} ( <Reputation reputation={player.workRepGained} /> (
{Reputation(`${numeralWrapper.formatExp(player.workRepGainRate * CYCLES_PER_SEC)} / sec`)} <ReputationRate reputation={player.workRepGainRate * CYCLES_PER_SEC} />
) reputation for this company <br /> ) reputation for this company <br />
<br /> <br />
{numeralWrapper.formatExp(player.workHackExpGained)} ( {numeralWrapper.formatExp(player.workHackExpGained)} (
@ -306,12 +307,12 @@ export function WorkInProgressRoot(): React.ReactElement {
<Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}> <Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
<Grid item> <Grid item>
<Typography> <Typography>
<p>You are attempting to {player.crimeType}.</p> <Typography>You are attempting to {player.crimeType}.</Typography>
<br /> <br />
<p> <Typography>
Time remaining: {convertTimeMsToTimeElapsedString(player.timeNeededToCompleteWork - player.timeWorked)} Time remaining: {convertTimeMsToTimeElapsedString(player.timeNeededToCompleteWork - player.timeWorked)}
</p> </Typography>
<br /> <br />
<pre>{progressBar}</pre> <pre>{progressBar}</pre>