Initial aug page overhaul work

This commit is contained in:
nickofolas 2022-04-07 17:53:58 -05:00
parent a9a31662ce
commit c94b4f4fd3
5 changed files with 456 additions and 220 deletions

@ -7,7 +7,7 @@ import React, { useState, useEffect } from "react";
import { InstalledAugmentations } from "./InstalledAugmentations";
import { PlayerMultipliers } from "./PlayerMultipliers";
import { PurchasedAugmentations } from "./PurchasedAugmentations";
import { SourceFiles } from "./SourceFiles";
import { SourceFilesElement } from "./SourceFiles";
import { canGetBonus } from "../../ExportBonus";
import { use } from "../../ui/Context";
@ -16,8 +16,53 @@ import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import Tooltip from "@mui/material/Tooltip";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Container from "@mui/material/Container";
import { Settings } from "../../Settings/Settings";
import { ConfirmationModal } from "../../ui/React/ConfirmationModal";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { AugmentationNames } from "../data/AugmentationNames";
import { Augmentations } from "../Augmentations";
import { CONSTANTS } from "../../Constants";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { Info } from "@mui/icons-material";
interface NFGDisplayProps {
player: IPlayer;
}
const NeuroFluxDisplay = ({ player }: NFGDisplayProps): React.ReactElement => {
const level = player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0;
return level > 0 ? (
<Paper sx={{ p: 1 }}>
<Typography variant="h5">NeuroFlux Governor - Level {level}</Typography>
<Typography>{Augmentations[AugmentationNames.NeuroFluxGovernor].stats}</Typography>
</Paper>
) : (
<></>
);
};
interface EntropyDisplayProps {
player: IPlayer;
}
const EntropyDisplay = ({ player }: EntropyDisplayProps): React.ReactElement => {
return player.entropy > 0 ? (
<Paper sx={{ p: 1 }}>
<Typography variant="h5" color={Settings.theme.hp}>
Entropy Virus - Level {player.entropy}
</Typography>
<Typography color={Settings.theme.hp}>
<b>All multipliers decreased by:</b> {formatNumber((1 - CONSTANTS.EntropyEffect ** player.entropy) * 100, 3)}%
(multiplicative)
</Typography>
</Paper>
) : (
<></>
);
};
interface IProps {
exportGameFn: () => void;
@ -55,81 +100,112 @@ export function AugmentationsRoot(props: IProps): React.ReactElement {
}
return (
<>
<Container disableGutters maxWidth="lg" sx={{ mx: 0 }}>
<Typography variant="h4">Augmentations</Typography>
<Box mx={2}>
<Typography>
Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to
install them.
</Typography>
<Typography>WARNING: Installing your Augmentations resets most of your progress, including:</Typography>
<br />
<Typography>- Stats/Skill levels and Experience</Typography>
<Typography>- Money</Typography>
<Typography>- Scripts on every computer but your home computer</Typography>
<Typography>- Purchased servers</Typography>
<Typography>- Hacknet Nodes</Typography>
<Typography>- Faction/Company reputation</Typography>
<Typography>- Stocks</Typography>
<br />
<Typography>
Installing Augmentations lets you start over with the perks and benefits granted by all of the Augmentations
you have ever installed. Also, you will keep any scripts and RAM/Core upgrades on your home computer (but you
will lose all programs besides NUKE.exe)
</Typography>
<Box sx={{ mb: 1 }}>
<Paper sx={{ p: 1 }}>
<Typography variant="h5" color="primary" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
Purchased Augmentations
<Tooltip
title={
<>
<Typography>
Below is a list of all Augmentations you have purchased but not yet installed. Click the button
below to install them.
</Typography>
<Typography>
WARNING: Installing your Augmentations resets most of your progress, including:
</Typography>
<br />
<Typography>- Stats/Skill levels and Experience</Typography>
<Typography>- Money</Typography>
<Typography>- Scripts on every computer but your home computer</Typography>
<Typography>- Purchased servers</Typography>
<Typography>- Hacknet Nodes</Typography>
<Typography>- Faction/Company reputation</Typography>
<Typography>- Stocks</Typography>
<br />
<Typography>
Installing Augmentations lets you start over with the perks and benefits granted by all of the
Augmentations you have ever installed. Also, you will keep any scripts and RAM/Core upgrades on your
home computer (but you will lose all programs besides NUKE.exe)
</Typography>
</>
}
>
<Info sx={{ ml: 1, mb: 1 }} color="info" />
</Tooltip>
</Typography>
<ConfirmationModal
open={installOpen}
onClose={() => setInstallOpen(false)}
onConfirm={props.installAugmentationsFn}
confirmationText={
<>
Installing will reset
<br />
<br />- money
<br />- skill / experience
<br />- every server except home
<br />- factions and reputation
<br />
<br />
You will keep:
<br />
<br />- All scripts on home
<br />- home ram and cores
<br />
<br />
It is recommended to install several Augmentations at once. Preferably everything from any faction of
your choosing.
</>
}
/>
<Box sx={{ display: "grid", width: "100%", gridTemplateColumns: "1fr 1fr" }}>
<Tooltip title={<Typography>'I never asked for this'</Typography>}>
<span>
<Button sx={{ width: "100%" }} disabled={player.queuedAugmentations.length === 0} onClick={doInstall}>
Install Augmentations
</Button>
</span>
</Tooltip>
<Tooltip title={<Typography>It's always a good idea to backup/export your save!</Typography>}>
<Button sx={{ width: "100%" }} onClick={doExport} color="error">
Backup Save {exportBonusStr()}
</Button>
</Tooltip>
</Box>
</Paper>
{player.queuedAugmentations.length > 0 ? (
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
<PurchasedAugmentations />
<PlayerMultipliers />
</Box>
) : (
<Paper sx={{ p: 1 }}>
<Typography>No Augmentations have been purchased yet</Typography>
</Paper>
)}
</Box>
<Typography variant="h4" color="primary">
Purchased Augmentations
</Typography>
<Box mx={2}>
<Tooltip title={<Typography>'I never asked for this'</Typography>}>
<span>
<Button disabled={player.queuedAugmentations.length === 0} onClick={doInstall}>
Install Augmentations
</Button>
</span>
</Tooltip>
<ConfirmationModal
open={installOpen}
onClose={() => setInstallOpen(false)}
onConfirm={props.installAugmentationsFn}
confirmationText={
<>
Installing will reset
<br />
<br />- money
<br />- skill / experience
<br />- every server except home
<br />- factions and reputation
<br />
<br />
You will keep:
<br />
<br />- All scripts on home
<br />- home ram and cores
<br />
<br />
It is recommended to install several Augmentations at once. Preferably everything from any faction of your
choosing.
</>
}
/>
<Tooltip title={<Typography>It's always a good idea to backup/export your save!</Typography>}>
<Button sx={{ mx: 2 }} onClick={doExport} color="error">
Backup Save {exportBonusStr()}
</Button>
</Tooltip>
<PurchasedAugmentations />
<Box
sx={{
my: 1,
display: "grid",
gridTemplateColumns: `repeat(${
+!!((player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0) > 0) +
+!!(player.entropy > 0)
}, 1fr)`,
}}
>
<NeuroFluxDisplay player={player} />
<EntropyDisplay player={player} />
</Box>
<Typography variant="h4">Installed Augmentations</Typography>
<Box mx={2}>
<Typography>
List of all Augmentations that have been installed. You have gained the effects of these.
</Typography>
<Box>
<InstalledAugmentations />
</Box>
<PlayerMultipliers />
<SourceFiles />
</>
<SourceFilesElement />
</Container>
);
}

@ -5,29 +5,24 @@
* It also contains 'configuration' buttons that allow you to change how the
* Augs/SF's are displayed
*/
import { Box, ListItemButton, Paper, Typography } from "@mui/material";
import Button from "@mui/material/Button";
import List from "@mui/material/List";
import Tooltip from "@mui/material/Tooltip";
import React, { useState } from "react";
import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion";
import { Augmentations } from "../Augmentations";
import { AugmentationNames } from "../data/AugmentationNames";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { Settings } from "../../Settings/Settings";
import { use } from "../../ui/Context";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import Button from "@mui/material/Button";
import Tooltip from "@mui/material/Tooltip";
import List from "@mui/material/List";
import { ExpandLess, ExpandMore } from "@mui/icons-material";
import { Box, Paper, ListItemButton, ListItemText, Typography, Collapse } from "@mui/material";
import { CONSTANTS } from "../../Constants";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { Augmentations } from "../Augmentations";
import { AugmentationNames } from "../data/AugmentationNames";
export function InstalledAugmentations(): React.ReactElement {
const setRerender = useState(true)[1];
const player = use.Player();
const sourceAugs = player.augmentations.slice();
const [selectedAug, setSelectedAug] = useState(sourceAugs[0]);
if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
sourceAugs.sort((aug1, aug2) => {
return aug1.name.localeCompare(aug2.name);
@ -49,59 +44,62 @@ export function InstalledAugmentations(): React.ReactElement {
}
return (
<>
<Tooltip title={"Sorts the Augmentations alphabetically in numeral order"}>
<Button onClick={sortInOrder}>Sort in Order</Button>
</Tooltip>
<Tooltip title={"Sorts the Augmentations based on when you acquired them (same as default)"}>
<Button sx={{ mx: 2 }} onClick={sortByAcquirementTime}>
Sort by Acquirement Time
</Button>
</Tooltip>
<List dense>
{player.entropy > 0 &&
(() => {
const [open, setOpen] = useState(false);
<Box sx={{ width: "100%" }}>
<Paper sx={{ p: 1 }}>
<Typography variant="h5">Installed Augmentations</Typography>
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
<Tooltip title={"Sorts the Augmentations alphabetically in numeral order"}>
<Button sx={{ width: "100%" }} onClick={sortInOrder}>
Sort in Order
</Button>
</Tooltip>
<Tooltip title={"Sorts the Augmentations based on when you acquired them (same as default)"}>
<Button sx={{ width: "100%" }} onClick={sortByAcquirementTime}>
Sort by Time of Acquirement
</Button>
</Tooltip>
</Box>
</Paper>
{sourceAugs.length > 0 ? (
<Paper sx={{ display: "grid", gridTemplateColumns: "1fr 3fr" }}>
<Box>
<List sx={{ maxHeight: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}>
{sourceAugs
.filter((aug) => aug.name !== AugmentationNames.NeuroFluxGovernor)
.map((k, i) => (
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
<Typography>{k.name}</Typography>
</ListItemButton>
))}
</List>
</Box>
<Box sx={{ m: 1 }}>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
{selectedAug.name}
</Typography>
<Typography sx={{ maxHeight: 305, overflowY: "scroll" }}>
{(() => {
const aug = Augmentations[selectedAug.name];
return (
<Box component={Paper}>
<ListItemButton onClick={() => setOpen((old) => !old)}>
<ListItemText
primary={
<Typography color={Settings.theme.hp} style={{ whiteSpace: "pre-wrap" }}>
Entropy Virus - Level {player.entropy}
</Typography>
}
/>
{open ? (
<ExpandLess sx={{ color: Settings.theme.hp }} />
) : (
<ExpandMore sx={{ color: Settings.theme.hp }} />
)}
</ListItemButton>
<Collapse in={open} unmountOnExit>
<Box m={4}>
<Typography color={Settings.theme.hp}>
<b>All multipliers decreased by:</b>{" "}
{formatNumber((1 - CONSTANTS.EntropyEffect ** player.entropy) * 100, 3)}% (multiplicative)
</Typography>
</Box>
</Collapse>
</Box>
);
})()}
{sourceAugs.map((e) => {
const aug = Augmentations[e.name];
let level = null;
if (e.name === AugmentationNames.NeuroFluxGovernor) {
level = e.level;
}
return <AugmentationAccordion key={aug.name} aug={aug} level={level} />;
})}
</List>
</>
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info;
const tooltip = (
<>
{info}
<br />
<br />
{aug.stats}
</>
);
return tooltip;
})()}
</Typography>
</Box>
</Paper>
) : (
<Paper sx={{ p: 1 }}>
<Typography>No Augmentations have been installed yet</Typography>
</Paper>
)}
</Box>
);
}

@ -1,17 +1,14 @@
/**
* React component for displaying the player's multipliers on the Augmentation UI page
*/
import { Box, Typography, List, ListItemText, ListItem, Paper } from "@mui/material";
import * as React from "react";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Player } from "../../Player";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Augmentations } from "../Augmentations";
import { Table, TableCell } from "../../ui/React/Table";
import TableBody from "@mui/material/TableBody";
import TableRow from "@mui/material/TableRow";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { DoubleArrow } from "@mui/icons-material";
import { Settings } from "../../Settings/Settings";
function calculateAugmentedStats(): any {
const augP: any = {};
@ -25,53 +22,63 @@ function calculateAugmentedStats(): any {
return augP;
}
function Improvements({ r, m }: { r: number; m: number }): React.ReactElement {
if (r) {
return (
<>
<TableCell key="2">
<Typography>&nbsp;{"=>"}&nbsp;</Typography>
</TableCell>
<TableCell key="3">
<Typography>
{numeralWrapper.formatPercentage(r)} <BN5Stat base={r} mult={m} />
</Typography>
</TableCell>
</>
);
}
return <></>;
}
interface IBN5StatsProps {
interface BitNodeModifiedStatsProps {
base: number;
mult: number;
color: string;
}
function BN5Stat(props: IBN5StatsProps): React.ReactElement {
if (props.mult === 1) return <></>;
return <>({numeralWrapper.formatPercentage(props.base * props.mult)})</>;
}
function BitNodeModifiedStats(props: BitNodeModifiedStatsProps): React.ReactElement {
if (props.mult === 1)
return <Typography color={props.color}>{numeralWrapper.formatPercentage(props.base)}</Typography>;
function MultiplierTable({ rows }: { rows: [string, number, number, number][] }): React.ReactElement {
return (
<Table size="small" padding="none">
<TableBody>
{rows.map((r: any) => (
<TableRow key={r[0]}>
<TableCell key="0">
<Typography noWrap>{r[0]} multiplier:&nbsp;</Typography>
</TableCell>
<TableCell key="1" style={{ textAlign: "right" }}>
<Typography noWrap>
{numeralWrapper.formatPercentage(r[1])} <BN5Stat base={r[1]} mult={r[3]} />
</Typography>
</TableCell>
<Improvements r={r[2]} m={r[3]} />
</TableRow>
))}
</TableBody>
</Table>
<Typography color={props.color}>
<span style={{ opacity: 0.5 }}>{numeralWrapper.formatPercentage(props.base)}</span>{" "}
{numeralWrapper.formatPercentage(props.base * props.mult)}
</Typography>
);
}
interface MultListProps {
rows: (string | number)[][];
color: string;
}
function MultiplierList(props: MultListProps): React.ReactElement {
return (
<List disablePadding>
{props.rows.map((data) => {
const mult = data[0] as string,
value = data[1] as number,
improved = data[2] as number | null,
bnMult = data[3] as number;
if (improved) {
return (
<ListItem key={mult} disableGutters sx={{ py: 0 }}>
<ListItemText
sx={{ my: 0.1 }}
primary={
<Typography color={props.color}>
<b>{mult}</b>
</Typography>
}
secondary={
<span style={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
<BitNodeModifiedStats base={value} mult={bnMult} color={props.color} />
<DoubleArrow fontSize="small" color="success" sx={{ mb: 1, mx: 1 }} />
<BitNodeModifiedStats base={improved} mult={bnMult} color={Settings.theme.success} />
</span>
}
disableTypography
/>
</ListItem>
);
}
return <></>;
})}
</List>
);
}
@ -82,7 +89,7 @@ export function PlayerMultipliers(): React.ReactElement {
if (!Player.canAccessBladeburner()) return <></>;
return (
<>
<MultiplierTable
<MultiplierList
rows={[
[
"Bladeburner Success Chance",
@ -109,6 +116,7 @@ export function PlayerMultipliers(): React.ReactElement {
1,
],
]}
color={Settings.theme.primary}
/>
<br />
</>
@ -116,20 +124,21 @@ export function PlayerMultipliers(): React.ReactElement {
}
return (
<>
<Typography variant="h4">Multipliers</Typography>
<Box mx={2}>
<MultiplierTable
<Paper sx={{ p: 1, maxHeight: 400, overflowY: "scroll" }}>
<Typography variant="h6">Multipliers</Typography>
<Box>
<MultiplierList
rows={[
["Hacking Chance ", Player.hacking_chance_mult, Player.hacking_chance_mult * mults.hacking_chance_mult, 1],
["Hacking Speed ", Player.hacking_speed_mult, Player.hacking_speed_mult * mults.hacking_speed_mult, 1],
["Hacking Money ", Player.hacking_money_mult, Player.hacking_money_mult * mults.hacking_money_mult, 1],
["Hacking Growth ", Player.hacking_grow_mult, Player.hacking_grow_mult * mults.hacking_grow_mult, 1],
]}
color={Settings.theme.hack}
/>
<br />
<MultiplierTable
<MultiplierList
rows={[
[
"Hacking Level ",
@ -144,10 +153,11 @@ export function PlayerMultipliers(): React.ReactElement {
BitNodeMultipliers.HackExpGain,
],
]}
color={Settings.theme.hack}
/>
<br />
<MultiplierTable
<MultiplierList
rows={[
[
"Strength Level ",
@ -157,10 +167,11 @@ export function PlayerMultipliers(): React.ReactElement {
],
["Strength Experience ", Player.strength_exp_mult, Player.strength_exp_mult * mults.strength_exp_mult, 1],
]}
color={Settings.theme.combat}
/>
<br />
<MultiplierTable
<MultiplierList
rows={[
[
"Defense Level ",
@ -170,10 +181,11 @@ export function PlayerMultipliers(): React.ReactElement {
],
["Defense Experience ", Player.defense_exp_mult, Player.defense_exp_mult * mults.defense_exp_mult, 1],
]}
color={Settings.theme.combat}
/>
<br />
<MultiplierTable
<MultiplierList
rows={[
[
"Dexterity Level ",
@ -188,10 +200,11 @@ export function PlayerMultipliers(): React.ReactElement {
1,
],
]}
color={Settings.theme.combat}
/>
<br />
<MultiplierTable
<MultiplierList
rows={[
[
"Agility Level ",
@ -201,10 +214,11 @@ export function PlayerMultipliers(): React.ReactElement {
],
["Agility Experience ", Player.agility_exp_mult, Player.agility_exp_mult * mults.agility_exp_mult, 1],
]}
color={Settings.theme.combat}
/>
<br />
<MultiplierTable
<MultiplierList
rows={[
[
"Charisma Level ",
@ -214,10 +228,11 @@ export function PlayerMultipliers(): React.ReactElement {
],
["Charisma Experience ", Player.charisma_exp_mult, Player.charisma_exp_mult * mults.charisma_exp_mult, 1],
]}
color={Settings.theme.cha}
/>
<br />
<MultiplierTable
<MultiplierList
rows={[
[
"Hacknet Node production ",
@ -250,10 +265,11 @@ export function PlayerMultipliers(): React.ReactElement {
1,
],
]}
color={Settings.theme.primary}
/>
<br />
<MultiplierTable
<MultiplierList
rows={[
["Company reputation gain ", Player.company_rep_mult, Player.company_rep_mult * mults.company_rep_mult, 1],
[
@ -269,10 +285,11 @@ export function PlayerMultipliers(): React.ReactElement {
BitNodeMultipliers.CompanyWorkMoney,
],
]}
color={Settings.theme.primary}
/>
<br />
<MultiplierTable
<MultiplierList
rows={[
["Crime success ", Player.crime_success_mult, Player.crime_success_mult * mults.crime_success_mult, 1],
[
@ -282,11 +299,12 @@ export function PlayerMultipliers(): React.ReactElement {
BitNodeMultipliers.CrimeMoney,
],
]}
color={Settings.theme.combat}
/>
<br />
<BladeburnerMults />
</Box>
</>
</Paper>
);
}

@ -9,7 +9,7 @@ import { AugmentationNames } from "../data/AugmentationNames";
import { Player } from "../../Player";
import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion";
import List from "@mui/material/List";
import { List, Paper } from "@mui/material";
export function PurchasedAugmentations(): React.ReactElement {
const augs: React.ReactElement[] = [];
@ -32,5 +32,9 @@ export function PurchasedAugmentations(): React.ReactElement {
augs.push(<AugmentationAccordion key={aug.name} aug={aug} level={level} />);
}
return <List dense>{augs}</List>;
return (
<Paper sx={{ p: 1, maxHeight: 400, overflowY: "scroll" }}>
<List dense>{augs}</List>
</Paper>
);
}

@ -1,21 +1,161 @@
import React from "react";
import { SourceFileMinus1 } from "./SourceFileMinus1";
import { OwnedSourceFiles } from "./OwnedSourceFiles";
import List from "@mui/material/List";
import Typography from "@mui/material/Typography";
import { ListItemButton, ListItemText, Paper } from "@mui/material";
import Box from "@mui/material/Box";
import List from "@mui/material/List";
import Typography from "@mui/material/Typography";
import React, { useState } from "react";
import { Exploit, ExploitName } from "../../Exploits/Exploit";
import { Player } from "../../Player";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { Settings } from "../../Settings/Settings";
import { SourceFile } from "../../SourceFile/SourceFile";
import { SourceFiles } from "../../SourceFile/SourceFiles";
interface SfMinus1 {
info: React.ReactElement;
n: number;
name: string;
}
const safeGetSf = (sfNum: number): SourceFile | SfMinus1 | null => {
if (sfNum === -1) {
return {
info: (
<>
This Source-File can only be acquired with obscure knowledge of the game, javascript, and the web ecosystem.
<br />
<br />
It increases all of the player's multipliers by 0.1%
<br />
<br />
You have found the following exploits:
<br />
<br />
{Player.exploits.map((c: Exploit) => (
<React.Fragment key={c}>
* {ExploitName(c)}
<br />
</React.Fragment>
))}
</>
),
lvl: Player.exploits.length,
n: -1,
name: "Source-File -1: Exploits in the BitNodes",
};
}
const srcFileKey = "SourceFile" + sfNum;
const sfObj = SourceFiles[srcFileKey];
if (sfObj == null) {
console.error(`Invalid source file number: ${sfNum}`);
return null;
}
return sfObj;
};
export function SourceFilesElement(): React.ReactElement {
const sourceSfs = Player.sourceFiles.slice();
const exploits = Player.exploits;
if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
sourceSfs.sort((sf1, sf2) => {
return sf1.n - sf2.n;
});
}
const [selectedSf, setSelectedSf] = useState<any>(sourceSfs[0]);
export function SourceFiles(): React.ReactElement {
return (
<>
<Typography variant="h4">Source Files</Typography>
<Box mx={2}>
<List dense>
<SourceFileMinus1 />
<OwnedSourceFiles />
</List>
</Box>
</>
<Box sx={{ width: "100%", mt: 1 }}>
<Paper sx={{ p: 1 }}>
<Typography variant="h5">Source Files</Typography>
</Paper>
{sourceSfs.length > 0 ? (
<Paper sx={{ display: "grid", gridTemplateColumns: "1fr 3fr" }}>
<Box>
<List
sx={{ maxHeight: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}
disablePadding
>
{exploits.length > 0 && (
<ListItemButton
key={-1}
onClick={() => setSelectedSf({ n: -1, lvl: exploits.length })}
selected={selectedSf.n === -1}
sx={{ py: 0 }}
>
<ListItemText
disableTypography
primary={<Typography>Source-File -1: Exploits in the BitNodes</Typography>}
secondary={
<Typography>
Level {exploits.length} / {Object.keys(Exploit).length}
</Typography>
}
/>
</ListItemButton>
)}
{sourceSfs.map((e, i) => {
const sfObj = safeGetSf(e.n);
const maxLevel = sfObj?.n === 12 ? "∞" : "3";
return (
<ListItemButton
key={i + 1}
onClick={() => setSelectedSf(e)}
selected={selectedSf === e}
sx={{ py: 0 }}
>
<ListItemText
disableTypography
primary={<Typography>{sfObj?.name}</Typography>}
secondary={
<Typography>
Level {selectedSf.lvl} / {maxLevel}
</Typography>
}
/>
</ListItemButton>
);
})}
</List>
</Box>
<Box sx={{ m: 1 }}>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
{safeGetSf(selectedSf.n)?.name}
</Typography>
<Typography sx={{ maxHeight: 305, overflowY: "scroll" }}>
{(() => {
const sfObj = safeGetSf(selectedSf.n);
let maxLevel;
switch (sfObj?.n) {
case 12:
maxLevel = "∞";
break;
case -1:
maxLevel = Object.keys(Exploit).length;
break;
default:
maxLevel = "3";
}
return (
<>
Level {selectedSf.lvl} / {maxLevel}
<br />
<br />
{sfObj?.info}
</>
);
})()}
</Typography>
</Box>
</Paper>
) : (
<></>
)}
</Box>
);
}