mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-21 08:42:53 +02:00
prettify, sorry for the big ass commit
This commit is contained in:
@@ -11,28 +11,28 @@ import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
workerScripts: Map<number, WorkerScript>;
|
||||
}
|
||||
p: IPlayer;
|
||||
workerScripts: Map<number, WorkerScript>;
|
||||
};
|
||||
|
||||
export class ActiveScriptsRoot extends React.Component<IProps> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
}
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
This page displays a list of all of your scripts that are currently
|
||||
running across every machine. It also provides information about each
|
||||
script's production. The scripts are categorized by the hostname of
|
||||
the servers on which they are running.
|
||||
</p>
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
This page displays a list of all of your scripts that are currently
|
||||
running across every machine. It also provides information about each
|
||||
script's production. The scripts are categorized by the hostname of
|
||||
the servers on which they are running.
|
||||
</p>
|
||||
|
||||
<ScriptProduction {...this.props} />
|
||||
<ServerAccordions {...this.props} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
<ScriptProduction {...this.props} />
|
||||
<ServerAccordions {...this.props} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,37 +9,42 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Money } from "../React/Money";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
workerScripts: Map<number, WorkerScript>;
|
||||
}
|
||||
p: IPlayer;
|
||||
workerScripts: Map<number, WorkerScript>;
|
||||
};
|
||||
|
||||
export function ScriptProduction(props: IProps): React.ReactElement {
|
||||
const prodRateSinceLastAug = props.p.scriptProdSinceLastAug / (props.p.playtimeSinceLastAug / 1000);
|
||||
const prodRateSinceLastAug =
|
||||
props.p.scriptProdSinceLastAug / (props.p.playtimeSinceLastAug / 1000);
|
||||
|
||||
let onlineProduction = 0;
|
||||
for (const ws of props.workerScripts.values()) {
|
||||
onlineProduction += (ws.scriptRef.onlineMoneyMade / ws.scriptRef.onlineRunningTime);
|
||||
}
|
||||
let onlineProduction = 0;
|
||||
for (const ws of props.workerScripts.values()) {
|
||||
onlineProduction +=
|
||||
ws.scriptRef.onlineMoneyMade / ws.scriptRef.onlineRunningTime;
|
||||
}
|
||||
|
||||
return (
|
||||
<p id="active-scripts-total-prod">
|
||||
Total online production of Active scripts:
|
||||
<span className="money-gold">
|
||||
<span id="active-scripts-total-production-active">
|
||||
<Money money={onlineProduction} />
|
||||
</span> / sec
|
||||
</span><br />
|
||||
|
||||
Total online production since last Aug installation:
|
||||
<span id="active-scripts-total-prod-aug-total" className="money-gold">
|
||||
<Money money={props.p.scriptProdSinceLastAug} />
|
||||
</span>
|
||||
|
||||
(<span className="money-gold">
|
||||
<span id="active-scripts-total-prod-aug-avg" className="money-gold">
|
||||
<Money money={prodRateSinceLastAug} />
|
||||
</span> / sec
|
||||
</span>)
|
||||
</p>
|
||||
)
|
||||
return (
|
||||
<p id="active-scripts-total-prod">
|
||||
Total online production of Active scripts:
|
||||
<span className="money-gold">
|
||||
<span id="active-scripts-total-production-active">
|
||||
<Money money={onlineProduction} />
|
||||
</span>{" "}
|
||||
/ sec
|
||||
</span>
|
||||
<br />
|
||||
Total online production since last Aug installation:
|
||||
<span id="active-scripts-total-prod-aug-total" className="money-gold">
|
||||
<Money money={props.p.scriptProdSinceLastAug} />
|
||||
</span>
|
||||
(
|
||||
<span className="money-gold">
|
||||
<span id="active-scripts-total-prod-aug-avg" className="money-gold">
|
||||
<Money money={prodRateSinceLastAug} />
|
||||
</span>{" "}
|
||||
/ sec
|
||||
</span>
|
||||
)
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,37 +14,37 @@ import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||
import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
|
||||
|
||||
type IProps = {
|
||||
server: BaseServer;
|
||||
workerScripts: WorkerScript[];
|
||||
}
|
||||
server: BaseServer;
|
||||
workerScripts: WorkerScript[];
|
||||
};
|
||||
|
||||
export function ServerAccordion(props: IProps): React.ReactElement {
|
||||
const server = props.server;
|
||||
const server = props.server;
|
||||
|
||||
// Accordion's header text
|
||||
// TODO: calculate the longest hostname length rather than hard coding it
|
||||
const longestHostnameLength = 18;
|
||||
const paddedName = `${server.hostname}${" ".repeat(longestHostnameLength)}`.slice(0, Math.max(server.hostname.length, longestHostnameLength));
|
||||
const barOptions = {
|
||||
progress: server.ramUsed / server.maxRam,
|
||||
totalTicks: 30,
|
||||
};
|
||||
const headerTxt = `${paddedName} ${createProgressBarText(barOptions)}`;
|
||||
|
||||
const scripts = props.workerScripts.map((ws) => {
|
||||
return (
|
||||
<WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />
|
||||
)
|
||||
});
|
||||
// Accordion's header text
|
||||
// TODO: calculate the longest hostname length rather than hard coding it
|
||||
const longestHostnameLength = 18;
|
||||
const paddedName = `${server.hostname}${" ".repeat(
|
||||
longestHostnameLength,
|
||||
)}`.slice(0, Math.max(server.hostname.length, longestHostnameLength));
|
||||
const barOptions = {
|
||||
progress: server.ramUsed / server.maxRam,
|
||||
totalTicks: 30,
|
||||
};
|
||||
const headerTxt = `${paddedName} ${createProgressBarText(barOptions)}`;
|
||||
|
||||
const scripts = props.workerScripts.map((ws) => {
|
||||
return (
|
||||
<Accordion
|
||||
headerContent={
|
||||
<pre>{headerTxt}</pre>
|
||||
}
|
||||
panelContent={
|
||||
<ServerAccordionContent workerScripts={props.workerScripts} />
|
||||
}
|
||||
/>
|
||||
)
|
||||
<WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Accordion
|
||||
headerContent={<pre>{headerTxt}</pre>}
|
||||
panelContent={
|
||||
<ServerAccordionContent workerScripts={props.workerScripts} />
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,78 +6,73 @@ import { AccordionButton } from "../React/AccordionButton";
|
||||
const pageSize = 20;
|
||||
|
||||
interface IProps {
|
||||
workerScripts: WorkerScript[];
|
||||
|
||||
workerScripts: WorkerScript[];
|
||||
}
|
||||
|
||||
export function ServerAccordionContent(props: IProps): React.ReactElement {
|
||||
if(props.workerScripts.length > pageSize) {
|
||||
return <ServerAccordionContentPaginated workerScripts={props.workerScripts} />
|
||||
if (props.workerScripts.length > pageSize) {
|
||||
return (
|
||||
<ServerAccordionContentPaginated workerScripts={props.workerScripts} />
|
||||
);
|
||||
}
|
||||
|
||||
const scripts = props.workerScripts.map((ws) => {
|
||||
return (
|
||||
<WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />
|
||||
);
|
||||
});
|
||||
|
||||
return <ul>{scripts}</ul>;
|
||||
}
|
||||
|
||||
export function ServerAccordionContentPaginated(
|
||||
props: IProps,
|
||||
): React.ReactElement {
|
||||
const [page, setPage] = useState(0);
|
||||
const scripts: React.ReactElement[] = [];
|
||||
const maxPage = Math.ceil(props.workerScripts.length / pageSize);
|
||||
const maxScript = Math.min((page + 1) * pageSize, props.workerScripts.length);
|
||||
for (let i = page * pageSize; i < maxScript; i++) {
|
||||
const ws = props.workerScripts[i];
|
||||
scripts.push(
|
||||
<WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />,
|
||||
);
|
||||
}
|
||||
|
||||
function capPage(page: number): number {
|
||||
if (page < 0) {
|
||||
page = 0;
|
||||
}
|
||||
|
||||
const scripts = props.workerScripts.map((ws) => {
|
||||
return (
|
||||
<WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />
|
||||
)
|
||||
if (maxPage - 1 < page) {
|
||||
page = maxPage - 1;
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
// in case we're on an invalid page number because scripts were killed.
|
||||
const capped = capPage(page);
|
||||
if (capped !== page) setPage(capped);
|
||||
|
||||
function changePage(n: number): void {
|
||||
setPage((newPage) => {
|
||||
newPage += n;
|
||||
newPage = Math.round(newPage);
|
||||
return capPage(newPage);
|
||||
});
|
||||
}
|
||||
|
||||
return (<ul>{scripts}</ul>);
|
||||
return (
|
||||
<>
|
||||
<ul>{scripts}</ul>
|
||||
<AccordionButton onClick={() => changePage(-1e99)} text="<<" />
|
||||
<AccordionButton onClick={() => changePage(-1)} text="<" />
|
||||
<span className="text">
|
||||
{page + 1} / {maxPage}
|
||||
</span>
|
||||
<AccordionButton onClick={() => changePage(1)} text=">" />
|
||||
<AccordionButton onClick={() => changePage(1e99)} text=">>" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export function ServerAccordionContentPaginated(props: IProps): React.ReactElement {
|
||||
const [page, setPage] = useState(0);
|
||||
const scripts: React.ReactElement[] = [];
|
||||
const maxPage = Math.ceil(props.workerScripts.length/pageSize);
|
||||
const maxScript = Math.min((page+1)*pageSize, props.workerScripts.length);
|
||||
for(let i = page*pageSize; i < maxScript; i++) {
|
||||
const ws = props.workerScripts[i];
|
||||
scripts.push(<WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />)
|
||||
}
|
||||
|
||||
function capPage(page: number): number {
|
||||
if(page < 0) {
|
||||
page = 0;
|
||||
}
|
||||
|
||||
if(maxPage-1 < page) {
|
||||
page = maxPage-1;
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
// in case we're on an invalid page number because scripts were killed.
|
||||
const capped = capPage(page);
|
||||
if(capped !== page)
|
||||
setPage(capped);
|
||||
|
||||
function changePage(n: number): void {
|
||||
setPage(newPage => {
|
||||
newPage += n;
|
||||
newPage = Math.round(newPage);
|
||||
return capPage(newPage);
|
||||
})
|
||||
}
|
||||
|
||||
return (<><ul>{scripts}</ul>
|
||||
<AccordionButton
|
||||
onClick={() => changePage(-1e99)}
|
||||
text="<<"
|
||||
/>
|
||||
<AccordionButton
|
||||
onClick={() => changePage(-1)}
|
||||
text="<"
|
||||
/>
|
||||
<span className="text">{page+1} / {maxPage}</span>
|
||||
<AccordionButton
|
||||
onClick={() => changePage(1)}
|
||||
text=">"
|
||||
/>
|
||||
<AccordionButton
|
||||
onClick={() => changePage(1e99)}
|
||||
text=">>"
|
||||
/>
|
||||
</>);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,97 +13,96 @@ import { BaseServer } from "../../Server/BaseServer";
|
||||
|
||||
// Map of server hostname -> all workerscripts on that server for all active scripts
|
||||
interface IServerData {
|
||||
server: BaseServer;
|
||||
workerScripts: WorkerScript[];
|
||||
server: BaseServer;
|
||||
workerScripts: WorkerScript[];
|
||||
}
|
||||
|
||||
interface IServerToScriptsMap {
|
||||
[key: string]: IServerData;
|
||||
[key: string]: IServerData;
|
||||
}
|
||||
|
||||
type IProps = {
|
||||
workerScripts: Map<number, WorkerScript>;
|
||||
workerScripts: Map<number, WorkerScript>;
|
||||
};
|
||||
|
||||
type IState = {
|
||||
rerenderFlag: boolean;
|
||||
}
|
||||
|
||||
rerenderFlag: boolean;
|
||||
};
|
||||
|
||||
const subscriberId = "ActiveScriptsUI";
|
||||
|
||||
export class ServerAccordions extends React.Component<IProps, IState> {
|
||||
serverToScriptMap: IServerToScriptsMap = {};
|
||||
serverToScriptMap: IServerToScriptsMap = {};
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
rerenderFlag: false,
|
||||
}
|
||||
this.state = {
|
||||
rerenderFlag: false,
|
||||
};
|
||||
|
||||
this.updateServerToScriptsMap();
|
||||
this.updateServerToScriptsMap();
|
||||
|
||||
this.rerender = this.rerender.bind(this);
|
||||
this.rerender = this.rerender.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
WorkerScriptStartStopEventEmitter.addSubscriber({
|
||||
cb: this.rerender,
|
||||
id: subscriberId,
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
WorkerScriptStartStopEventEmitter.removeSubscriber(subscriberId);
|
||||
}
|
||||
|
||||
updateServerToScriptsMap(): void {
|
||||
const map: IServerToScriptsMap = {};
|
||||
|
||||
for (const ws of this.props.workerScripts.values()) {
|
||||
const server = getServer(ws.serverIp);
|
||||
if (server == null) {
|
||||
console.warn(`WorkerScript has invalid IP address: ${ws.serverIp}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (map[server.hostname] == null) {
|
||||
map[server.hostname] = {
|
||||
server: server,
|
||||
workerScripts: [],
|
||||
};
|
||||
}
|
||||
|
||||
map[server.hostname].workerScripts.push(ws);
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
WorkerScriptStartStopEventEmitter.addSubscriber({
|
||||
cb: this.rerender,
|
||||
id: subscriberId,
|
||||
})
|
||||
}
|
||||
this.serverToScriptMap = map;
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
WorkerScriptStartStopEventEmitter.removeSubscriber(subscriberId);
|
||||
}
|
||||
rerender(): void {
|
||||
this.updateServerToScriptsMap();
|
||||
this.setState((prevState) => {
|
||||
return { rerenderFlag: !prevState.rerenderFlag };
|
||||
});
|
||||
}
|
||||
|
||||
updateServerToScriptsMap(): void {
|
||||
const map: IServerToScriptsMap = {};
|
||||
render(): React.ReactNode {
|
||||
const elems = Object.keys(this.serverToScriptMap).map((serverName) => {
|
||||
const data = this.serverToScriptMap[serverName];
|
||||
return (
|
||||
<ServerAccordion
|
||||
key={serverName}
|
||||
server={data.server}
|
||||
workerScripts={data.workerScripts}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
for (const ws of this.props.workerScripts.values()) {
|
||||
const server = getServer(ws.serverIp);
|
||||
if (server == null) {
|
||||
console.warn(`WorkerScript has invalid IP address: ${ws.serverIp}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (map[server.hostname] == null) {
|
||||
map[server.hostname] = {
|
||||
server: server,
|
||||
workerScripts: [],
|
||||
};
|
||||
}
|
||||
|
||||
map[server.hostname].workerScripts.push(ws);
|
||||
}
|
||||
|
||||
this.serverToScriptMap = map;
|
||||
}
|
||||
|
||||
rerender(): void {
|
||||
this.updateServerToScriptsMap();
|
||||
this.setState((prevState) => {
|
||||
return { rerenderFlag: !prevState.rerenderFlag }
|
||||
});
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
const elems = Object.keys(this.serverToScriptMap).map((serverName) => {
|
||||
const data = this.serverToScriptMap[serverName];
|
||||
return (
|
||||
<ServerAccordion
|
||||
key={serverName}
|
||||
server={data.server}
|
||||
workerScripts={data.workerScripts}
|
||||
/>
|
||||
)
|
||||
});
|
||||
|
||||
return (
|
||||
<ul className="active-scripts-list" id="active-scripts-list">
|
||||
{elems}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<ul className="active-scripts-list" id="active-scripts-list">
|
||||
{elems}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,59 +19,96 @@ import { arrayToString } from "../../../utils/helpers/arrayToString";
|
||||
import { Money } from "../React/Money";
|
||||
|
||||
type IProps = {
|
||||
workerScript: WorkerScript;
|
||||
}
|
||||
workerScript: WorkerScript;
|
||||
};
|
||||
|
||||
export function WorkerScriptAccordion(props: IProps): React.ReactElement {
|
||||
const workerScript = props.workerScript;
|
||||
const scriptRef = workerScript.scriptRef;
|
||||
const workerScript = props.workerScript;
|
||||
const scriptRef = workerScript.scriptRef;
|
||||
|
||||
const logClickHandler = logBoxCreate.bind(null, scriptRef);
|
||||
const killScript = killWorkerScript.bind(null, scriptRef as any, scriptRef.server);
|
||||
const logClickHandler = logBoxCreate.bind(null, scriptRef);
|
||||
const killScript = killWorkerScript.bind(
|
||||
null,
|
||||
scriptRef as any,
|
||||
scriptRef.server,
|
||||
);
|
||||
|
||||
function killScriptClickHandler(): void {
|
||||
killScript();
|
||||
dialogBoxCreate("Killing script");
|
||||
}
|
||||
function killScriptClickHandler(): void {
|
||||
killScript();
|
||||
dialogBoxCreate("Killing script");
|
||||
}
|
||||
|
||||
// Calculations for script stats
|
||||
const onlineMps = scriptRef.onlineMoneyMade / scriptRef.onlineRunningTime;
|
||||
const onlineEps = scriptRef.onlineExpGained / scriptRef.onlineRunningTime;
|
||||
const offlineMps = scriptRef.offlineMoneyMade / scriptRef.offlineRunningTime;
|
||||
const offlineEps = scriptRef.offlineExpGained / scriptRef.offlineRunningTime;
|
||||
// Calculations for script stats
|
||||
const onlineMps = scriptRef.onlineMoneyMade / scriptRef.onlineRunningTime;
|
||||
const onlineEps = scriptRef.onlineExpGained / scriptRef.onlineRunningTime;
|
||||
const offlineMps = scriptRef.offlineMoneyMade / scriptRef.offlineRunningTime;
|
||||
const offlineEps = scriptRef.offlineExpGained / scriptRef.offlineRunningTime;
|
||||
|
||||
return (
|
||||
<Accordion
|
||||
headerClass="active-scripts-script-header"
|
||||
headerContent={
|
||||
<>{props.workerScript.name}</>
|
||||
}
|
||||
panelClass="active-scripts-script-panel"
|
||||
panelContent={
|
||||
<>
|
||||
<pre>Threads: {numeralWrapper.formatThreads(props.workerScript.scriptRef.threads)}</pre>
|
||||
<pre>Args: {arrayToString(props.workerScript.args)}</pre>
|
||||
<pre>Online Time: {convertTimeMsToTimeElapsedString(scriptRef.onlineRunningTime * 1e3)}</pre>
|
||||
<pre>Offline Time: {convertTimeMsToTimeElapsedString(scriptRef.offlineRunningTime * 1e3)}</pre>
|
||||
<pre>Total online production: <Money money={scriptRef.onlineMoneyMade} /></pre>
|
||||
<pre>{(Array(26).join(" ") + numeralWrapper.formatExp(scriptRef.onlineExpGained) + " hacking exp")}</pre>
|
||||
<pre>Online production rate: <Money money={onlineMps} /> / second</pre>
|
||||
<pre>{(Array(25).join(" ") + numeralWrapper.formatExp(onlineEps) + " hacking exp / second")}</pre>
|
||||
<pre>Total offline production: <Money money={scriptRef.offlineMoneyMade} /></pre>
|
||||
<pre>{(Array(27).join(" ") + numeralWrapper.formatExp(scriptRef.offlineExpGained) + " hacking exp")}</pre>
|
||||
<pre>Offline production rate: <Money money={offlineMps} /> / second</pre>
|
||||
<pre>{(Array(26).join(" ") + numeralWrapper.formatExp(offlineEps) + " hacking exp / second")}</pre>
|
||||
return (
|
||||
<Accordion
|
||||
headerClass="active-scripts-script-header"
|
||||
headerContent={<>{props.workerScript.name}</>}
|
||||
panelClass="active-scripts-script-panel"
|
||||
panelContent={
|
||||
<>
|
||||
<pre>
|
||||
Threads:{" "}
|
||||
{numeralWrapper.formatThreads(props.workerScript.scriptRef.threads)}
|
||||
</pre>
|
||||
<pre>Args: {arrayToString(props.workerScript.args)}</pre>
|
||||
<pre>
|
||||
Online Time:{" "}
|
||||
{convertTimeMsToTimeElapsedString(
|
||||
scriptRef.onlineRunningTime * 1e3,
|
||||
)}
|
||||
</pre>
|
||||
<pre>
|
||||
Offline Time:{" "}
|
||||
{convertTimeMsToTimeElapsedString(
|
||||
scriptRef.offlineRunningTime * 1e3,
|
||||
)}
|
||||
</pre>
|
||||
<pre>
|
||||
Total online production: <Money money={scriptRef.onlineMoneyMade} />
|
||||
</pre>
|
||||
<pre>
|
||||
{Array(26).join(" ") +
|
||||
numeralWrapper.formatExp(scriptRef.onlineExpGained) +
|
||||
" hacking exp"}
|
||||
</pre>
|
||||
<pre>
|
||||
Online production rate: <Money money={onlineMps} /> / second
|
||||
</pre>
|
||||
<pre>
|
||||
{Array(25).join(" ") +
|
||||
numeralWrapper.formatExp(onlineEps) +
|
||||
" hacking exp / second"}
|
||||
</pre>
|
||||
<pre>
|
||||
Total offline production:{" "}
|
||||
<Money money={scriptRef.offlineMoneyMade} />
|
||||
</pre>
|
||||
<pre>
|
||||
{Array(27).join(" ") +
|
||||
numeralWrapper.formatExp(scriptRef.offlineExpGained) +
|
||||
" hacking exp"}
|
||||
</pre>
|
||||
<pre>
|
||||
Offline production rate: <Money money={offlineMps} /> / second
|
||||
</pre>
|
||||
<pre>
|
||||
{Array(26).join(" ") +
|
||||
numeralWrapper.formatExp(offlineEps) +
|
||||
" hacking exp / second"}
|
||||
</pre>
|
||||
|
||||
<AccordionButton
|
||||
onClick={logClickHandler}
|
||||
text="Log"
|
||||
/>
|
||||
<AccordionButton
|
||||
onClick={killScriptClickHandler}
|
||||
text="Kill Script"
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)
|
||||
<AccordionButton onClick={logClickHandler} text="Log" />
|
||||
<AccordionButton
|
||||
onClick={killScriptClickHandler}
|
||||
text="Kill Script"
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user