Finished refactoring Active Scripts UI into React/TypeScript. Currently untested

This commit is contained in:
danielyxie
2019-05-16 23:44:59 -07:00
parent 42804b0cd3
commit c1ec3c5eba
14 changed files with 460 additions and 510 deletions
+7
View File
@@ -4,9 +4,14 @@
*/
import * as React from "react";
import { ScriptProduction } from "./ScriptProduction";
import { ServerAccordions } from "./ServerAccordions";
import { WorkerScript } from "../../Netscript/WorkerScript";
import { IPlayer } from "../../PersonObjects/IPlayer";
type IProps = {
p: IPlayer;
workerScripts: WorkerScript[];
}
@@ -25,6 +30,8 @@ export class ActiveScriptsRoot extends React.Component<IProps, any> {
the servers on which they are running.
</p>
<ScriptProduction {...this.props} />
<ServerAccordions {...this.props} />
</>
)
}
+45
View File
@@ -0,0 +1,45 @@
/**
* React Component for displaying the total production and production rate
* of scripts on the 'Active Scripts' UI page
*/
import * as React from "react";
import { numeralWrapper } from "../numeralFormat";
import { WorkerScript } from "../../Netscript/WorkerScript";
import { IPlayer } from "../../PersonObjects/IPlayer";
type IProps = {
p: IPlayer;
workerScripts: WorkerScript[];
}
export function ScriptProduction(props: IProps): React.ReactElement {
const prodRateSinceLastAug = props.p.scriptProdSinceLastAug / (props.p.playtimeSinceLastAug / 1000);
let onlineProduction = 0;
for (const ws of props.workerScripts) {
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">
{numeralWrapper.formatMoney(onlineProduction)}
</span> / sec
</span><br />
Total online production since last Aug installation:
<span id="active-scripts-total-prod-aug-total" className="money-gold">
{numeralWrapper.formatMoney(props.p.scriptProdSinceLastAug)}
</span>
(<span className="money-gold">
<span id="active-scripts-total-prod-aug-avg" className="money-gold">
{numeralWrapper.formatMoney(prodRateSinceLastAug)}
</span> / sec
</span>)
</p>
)
}
+49
View File
@@ -0,0 +1,49 @@
/**
* React Component for rendering the Accordion element for a single
* server in the 'Active Scripts' UI page
*/
import * as React from "react";
import { WorkerScriptAccordion } from "./WorkerScriptAccordion";
import { Accordion } from "../React/Accordion";
import { BaseServer } from "../../Server/BaseServer";
import { WorkerScript } from "../../Netscript/WorkerScript";
import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
type IProps = {
server: BaseServer;
workerScripts: WorkerScript[];
}
export function ServerAccordion(props: IProps): React.ReactElement {
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)}`.replace(/\s/g, '&nbsp;');
const scripts = props.workerScripts.map((ws) => {
return (
<WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />
)
});
return (
<Accordion
headerContent={
<p>{headerTxt}</p>
}
panelContent={
<ul>{scripts}</ul>
}
/>
)
}
+81
View File
@@ -0,0 +1,81 @@
/**
* React Component for rendering the Accordion elements for all servers
* on which scripts are running
*/
import * as React from "react";
import { ServerAccordion } from "./ServerAccordion";
import { getServer } from "../../Server/ServerHelpers";
import { BaseServer } from "../../Server/BaseServer";
import { WorkerScript } from "../../Netscript/WorkerScript";
// Map of server hostname -> all workerscripts on that server for all active scripts
interface IServerData {
server: BaseServer;
workerScripts: WorkerScript[];
}
interface IServerToScriptsMap {
[key: string]: IServerData;
}
type IProps = {
workerScripts: WorkerScript[];
};
export class ServerAccordions extends React.Component<IProps> {
serverToScriptMap: IServerToScriptsMap = {};
constructor(props: IProps) {
super(props);
this.updateServerToScriptsMap();
// TODO
// We subscribe to an event emitter that publishes whenever a script is
// started/stopped. This allows us to only update the map when necessary
}
updateServerToScriptsMap(): void {
const map: IServerToScriptsMap = {};
for (const ws of this.props.workerScripts) {
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;
}
render() {
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>
)
}
}
+38 -7
View File
@@ -4,10 +4,16 @@
*/
import * as React from "react";
import { Accordion } from "../React/Accordion";
import { numeralWrapper } from "../numeralFormat";
import { Accordion } from "../React/Accordion";
import { AccordionButton } from "../React/AccordionButton";
import { killWorkerScript } from "../../Netscript/killWorkerScript";
import { WorkerScript } from "../../Netscript/WorkerScript";
import { logBoxCreate } from "../../../utils/LogBox";
import { convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions";
import { arrayToString } from "../../../utils/helpers/arrayToString";
type IProps = {
@@ -15,7 +21,17 @@ type IProps = {
}
export function WorkerScriptAccordion(props: IProps): React.ReactElement {
const workerScript = props.workerScript;
const scriptRef = workerScript.scriptRef;
const logClickHandler = logBoxCreate.bind(null, scriptRef);
const killScriptButton = killWorkerScript.bind(null, scriptRef, scriptRef.server);
// 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
@@ -27,12 +43,27 @@ export function WorkerScriptAccordion(props: IProps): React.ReactElement {
panelClass="active-scripts-script-panel"
panelContent={
<>
<p>
Threads: {props.workerScript.scriptRef.threads}
</p>
<p>
Args: {arrayToString(props.workerScript.args)}
</p>
<p>Threads: {props.workerScript.scriptRef.threads}</p>
<p>Args: {arrayToString(props.workerScript.args)}</p>
<p>Online Time: {convertTimeMsToTimeElapsedString(scriptRef.onlineRunningTime * 1e3)}</p>
<p>Offline Time: {convertTimeMsToTimeElapsedString(scriptRef.offlineRunningTime * 1e3)}</p>
<p>Total online production: {numeralWrapper.formatMoney(scriptRef.onlineMoneyMade)}</p>
<p>{(Array(26).join(" ") + numeralWrapper.formatBigNumber(scriptRef.onlineExpGained) + " hacking exp").replace( / /g, "&nbsp;")}</p>
<p>Online production rate: {numeralWrapper.formatMoney(onlineMps)} / second</p>
<p>{(Array(25).join(" ") + numeralWrapper.formatBigNumber(onlineEps) + " hacking exp / second").replace( / /g, "&nbsp;")}</p>
<p>Total offline production: {numeralWrapper.formatMoney(scriptRef.offlineMoneyMade)}</p>
<p>{(Array(27).join(" ") + numeralWrapper.formatBigNumber(scriptRef.offlineExpGained) + " hacking exp").replace( / /g, "&nbsp;")}</p>
<p>Offline production rate: {numeralWrapper.formatMoney(offlineMps)} / second</p>
<p>{(Array(26).join(" ") + numeralWrapper.formatBigNumber(offlineEps) + " hacking exp / second").replace( / /g, "&nbsp;")}</p>
<AccordionButton
onClick={logClickHandler}
text="Log"
/>
<AccordionButton
onClick={killScriptButton}
text="Kill Script"
/>
</>
}
/>