one big container ready

This commit is contained in:
Olivier Gagnon 2021-09-17 02:31:19 -04:00
parent 4a3658ea13
commit 1883bea906
8 changed files with 82 additions and 122 deletions

@ -119,13 +119,7 @@ import { SpecialServerIps } from "./Server/SpecialServerIps";
import { SourceFileFlags } from "./SourceFile/SourceFileFlags"; import { SourceFileFlags } from "./SourceFile/SourceFileFlags";
import { buyStock, sellStock, shortStock, sellShort } from "./StockMarket/BuyingAndSelling"; import { buyStock, sellStock, shortStock, sellShort } from "./StockMarket/BuyingAndSelling";
import { influenceStockThroughServerHack, influenceStockThroughServerGrow } from "./StockMarket/PlayerInfluencing"; import { influenceStockThroughServerHack, influenceStockThroughServerGrow } from "./StockMarket/PlayerInfluencing";
import { import { StockMarket, SymbolToStockMap, placeOrder, cancelOrder } from "./StockMarket/StockMarket";
StockMarket,
SymbolToStockMap,
placeOrder,
cancelOrder,
displayStockMarketContent,
} from "./StockMarket/StockMarket";
import { getBuyTransactionCost, getSellTransactionGain } from "./StockMarket/StockMarketHelpers"; import { getBuyTransactionCost, getSellTransactionGain } from "./StockMarket/StockMarketHelpers";
import { OrderTypes } from "./StockMarket/data/OrderTypes"; import { OrderTypes } from "./StockMarket/data/OrderTypes";
import { PositionTypes } from "./StockMarket/data/PositionTypes"; import { PositionTypes } from "./StockMarket/data/PositionTypes";
@ -1964,18 +1958,14 @@ function NetscriptFunctions(workerScript) {
updateDynamicRam("buyStock", getRamCost("buyStock")); updateDynamicRam("buyStock", getRamCost("buyStock"));
checkTixApiAccess("buyStock"); checkTixApiAccess("buyStock");
const stock = getStockFromSymbol(symbol, "buyStock"); const stock = getStockFromSymbol(symbol, "buyStock");
const res = buyStock(stock, shares, workerScript, { const res = buyStock(stock, shares, workerScript, {});
rerenderFn: displayStockMarketContent,
});
return res ? stock.price : 0; return res ? stock.price : 0;
}, },
sellStock: function (symbol, shares) { sellStock: function (symbol, shares) {
updateDynamicRam("sellStock", getRamCost("sellStock")); updateDynamicRam("sellStock", getRamCost("sellStock"));
checkTixApiAccess("sellStock"); checkTixApiAccess("sellStock");
const stock = getStockFromSymbol(symbol, "sellStock"); const stock = getStockFromSymbol(symbol, "sellStock");
const res = sellStock(stock, shares, workerScript, { const res = sellStock(stock, shares, workerScript, {});
rerenderFn: displayStockMarketContent,
});
return res ? stock.price : 0; return res ? stock.price : 0;
}, },
@ -1991,9 +1981,7 @@ function NetscriptFunctions(workerScript) {
} }
} }
const stock = getStockFromSymbol(symbol, "shortStock"); const stock = getStockFromSymbol(symbol, "shortStock");
const res = shortStock(stock, shares, workerScript, { const res = shortStock(stock, shares, workerScript, {});
rerenderFn: displayStockMarketContent,
});
return res ? stock.price : 0; return res ? stock.price : 0;
}, },
@ -2009,9 +1997,7 @@ function NetscriptFunctions(workerScript) {
} }
} }
const stock = getStockFromSymbol(symbol, "sellShort"); const stock = getStockFromSymbol(symbol, "sellShort");
const res = sellShort(stock, shares, workerScript, { const res = sellShort(stock, shares, workerScript, {});
rerenderFn: displayStockMarketContent,
});
return res ? stock.price : 0; return res ? stock.price : 0;
}, },
@ -2168,7 +2154,6 @@ function NetscriptFunctions(workerScript) {
Player.has4SData = true; Player.has4SData = true;
Player.loseMoney(getStockMarket4SDataCost()); Player.loseMoney(getStockMarket4SDataCost());
workerScript.log("purchase4SMarketData", "Purchased 4S Market Data"); workerScript.log("purchase4SMarketData", "Purchased 4S Market Data");
displayStockMarketContent();
return true; return true;
}, },
purchase4SMarketDataTixApi: function () { purchase4SMarketDataTixApi: function () {
@ -2188,7 +2173,6 @@ function NetscriptFunctions(workerScript) {
Player.has4SDataTixApi = true; Player.has4SDataTixApi = true;
Player.loseMoney(getStockMarket4STixApiCost()); Player.loseMoney(getStockMarket4STixApiCost());
workerScript.log("purchase4SMarketDataTixApi", "Purchased 4S Market Data TIX API"); workerScript.log("purchase4SMarketDataTixApi", "Purchased 4S Market Data TIX API");
displayStockMarketContent();
return true; return true;
}, },
getPurchasedServerLimit: function () { getPurchasedServerLimit: function () {

@ -25,9 +25,9 @@ export function ProgramsRoot(props: IProps): React.ReactElement {
<div> <div>
<Box> <Box>
<Typography> <Typography>
This page displays any programs that you are able to create. Writing the code for a program takes time, which This page displays any programs that you are able to create. Writing the code for a program takes time,
can vary based on how complex the program is. If you are working on creating a program you can cancel at any which can vary based on how complex the program is. If you are working on creating a program you can cancel
time. Your progress will be saved and you can continue later. at any time. Your progress will be saved and you can continue later.
</Typography> </Typography>
</Box> </Box>
<ButtonGroup> <ButtonGroup>
@ -36,15 +36,15 @@ export function ProgramsRoot(props: IProps): React.ReactElement {
if (create === null) return <></>; if (create === null) return <></>;
return ( return (
<Tooltip title={create.tooltip}> <Tooltip key={program.name} title={create.tooltip}>
<Button onClick={() => props.player.startCreateProgramWork(program.name, create.time, create.level)}> <Button onClick={() => props.player.startCreateProgramWork(program.name, create.time, create.level)}>
{program.name} {program.name}
</Button> </Button>
</Tooltip> </Tooltip>
) );
})} })}
</ButtonGroup> </ButtonGroup>
</div> </div>
</> </>
) );
} }

@ -21,7 +21,6 @@ import { dialogBoxCreate } from "../../utils/DialogBox";
import * as React from "react"; import * as React from "react";
export interface IProcessOrderRefs { export interface IProcessOrderRefs {
rerenderFn: () => void;
stockMarket: IStockMarket; stockMarket: IStockMarket;
symbolToStockMap: IMap<Stock>; symbolToStockMap: IMap<Stock>;
} }
@ -116,7 +115,6 @@ function executeOrder(order: Order, refs: IProcessOrderRefs): void {
// When orders are executed, the buying and selling functions shouldn't // When orders are executed, the buying and selling functions shouldn't
// emit popup dialog boxes. This options object configures the functions for that // emit popup dialog boxes. This options object configures the functions for that
const opts = { const opts = {
rerenderFn: refs.rerenderFn,
suppressDialog: true, suppressDialog: true,
}; };
@ -158,7 +156,6 @@ function executeOrder(order: Order, refs: IProcessOrderRefs): void {
{numeralWrapper.formatShares(Math.round(order.shares))} shares) {numeralWrapper.formatShares(Math.round(order.shares))} shares)
</>, </>,
); );
refs.rerenderFn();
return; return;
} }
} }

@ -26,7 +26,12 @@ import { Reviver } from "../../utils/JSONReviver";
import * as React from "react"; import * as React from "react";
import * as ReactDOM from "react-dom"; import * as ReactDOM from "react-dom";
export let StockMarket: IStockMarket | IMap<any> = {}; // Maps full stock name -> Stock object export let StockMarket: IStockMarket = {
lastUpdate: 0,
Orders: {},
storedCycles: 0,
ticksUntilCycle: 0,
} as IStockMarket; // Maps full stock name -> Stock object
export const SymbolToStockMap: IMap<Stock> = {}; // Maps symbol -> Stock object export const SymbolToStockMap: IMap<Stock> = {}; // Maps symbol -> Stock object
export function placeOrder( export function placeOrder(
@ -70,12 +75,10 @@ export function placeOrder(
// Process to see if it should be executed immediately // Process to see if it should be executed immediately
const processOrderRefs = { const processOrderRefs = {
rerenderFn: displayStockMarketContent,
stockMarket: StockMarket as IStockMarket, stockMarket: StockMarket as IStockMarket,
symbolToStockMap: SymbolToStockMap, symbolToStockMap: SymbolToStockMap,
}; };
processOrders(stock, order.type, order.pos, processOrderRefs); processOrders(stock, order.type, order.pos, processOrderRefs);
displayStockMarketContent();
return true; return true;
} }
@ -100,7 +103,6 @@ export function cancelOrder(params: ICancelOrderParams, workerScript: WorkerScri
for (let i = 0; i < stockOrders.length; ++i) { for (let i = 0; i < stockOrders.length; ++i) {
if (order == stockOrders[i]) { if (order == stockOrders[i]) {
stockOrders.splice(i, 1); stockOrders.splice(i, 1);
displayStockMarketContent();
return true; return true;
} }
} }
@ -125,7 +127,6 @@ export function cancelOrder(params: ICancelOrderParams, workerScript: WorkerScri
params.pos === order.pos params.pos === order.pos
) { ) {
stockOrders.splice(i, 1); stockOrders.splice(i, 1);
displayStockMarketContent();
if (workerScript) { if (workerScript) {
workerScript.scriptRef.log("Successfully cancelled order: " + orderTxt); workerScript.scriptRef.log("Successfully cancelled order: " + orderTxt);
} }
@ -142,14 +143,25 @@ export function cancelOrder(params: ICancelOrderParams, workerScript: WorkerScri
export function loadStockMarket(saveString: string): void { export function loadStockMarket(saveString: string): void {
if (saveString === "") { if (saveString === "") {
StockMarket = {}; StockMarket = {
lastUpdate: 0,
Orders: {},
storedCycles: 0,
ticksUntilCycle: 0,
} as IStockMarket;
} else { } else {
console.log(JSON.parse(saveString, Reviver));
StockMarket = JSON.parse(saveString, Reviver); StockMarket = JSON.parse(saveString, Reviver);
} }
} }
export function deleteStockMarket(): void { export function deleteStockMarket(): void {
StockMarket = {}; StockMarket = {
lastUpdate: 0,
Orders: {},
storedCycles: 0,
ticksUntilCycle: 0,
} as IStockMarket;
} }
export function initStockMarket(): void { export function initStockMarket(): void {
@ -269,8 +281,7 @@ export function processStockPrices(numCycles = 1): void {
const c = Math.random(); const c = Math.random();
const processOrderRefs = { const processOrderRefs = {
rerenderFn: displayStockMarketContent, stockMarket: StockMarket,
stockMarket: StockMarket as IStockMarket,
symbolToStockMap: SymbolToStockMap, symbolToStockMap: SymbolToStockMap,
}; };
if (c < chc) { if (c < chc) {
@ -301,8 +312,6 @@ export function processStockPrices(numCycles = 1): void {
// Shares required for price movement gradually approaches max over time // Shares required for price movement gradually approaches max over time
stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovement + 10, stock.shareTxForMovement); stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovement + 10, stock.shareTxForMovement);
} }
displayStockMarketContent();
} }
let stockMarketContainer: HTMLElement | null = null; let stockMarketContainer: HTMLElement | null = null;
@ -313,36 +322,9 @@ function setStockMarketContainer(): void {
document.addEventListener("DOMContentLoaded", setStockMarketContainer); document.addEventListener("DOMContentLoaded", setStockMarketContainer);
function initStockMarketFnForReact(): void { export function initStockMarketFnForReact(): void {
initStockMarket(); initStockMarket();
initSymbolToStockMap(); initSymbolToStockMap();
} }
const eventEmitterForUiReset = new EventEmitter(); export const eventEmitterForUiReset = new EventEmitter();
export function displayStockMarketContent(): void {
if (!routing.isOn(Page.StockMarket)) {
return;
}
eventEmitterForUiReset.emitEvent();
if (stockMarketContainer instanceof HTMLElement) {
const castedStockMarket = StockMarket as IStockMarket;
ReactDOM.render(
<StockMarketRoot
buyStockLong={buyStock}
buyStockShort={shortStock}
cancelOrder={cancelOrder}
eventEmitterForReset={eventEmitterForUiReset}
initStockMarket={initStockMarketFnForReact}
p={Player}
placeOrder={placeOrder}
sellStockLong={sellStock}
sellStockShort={sellShort}
stockMarket={castedStockMarket}
/>,
stockMarketContainer,
);
}
}

@ -1,7 +1,7 @@
/** /**
* Root React component for the Stock Market UI * Root React component for the Stock Market UI
*/ */
import * as React from "react"; import React, { useState, useEffect } from "react";
import { InfoAndPurchases } from "./InfoAndPurchases"; import { InfoAndPurchases } from "./InfoAndPurchases";
import { StockTickers } from "./StockTickers"; import { StockTickers } from "./StockTickers";
@ -36,47 +36,32 @@ type IProps = {
stockMarket: IStockMarket; stockMarket: IStockMarket;
}; };
type IState = { export function StockMarketRoot(props: IProps) {
rerenderFlag: boolean; const setRerender = useState(false)[1];
}; function rerender(): void {
setRerender((old) => !old);
export class StockMarketRoot extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
this.state = {
rerenderFlag: false,
};
this.rerender = this.rerender.bind(this);
} }
rerender(): void { useEffect(() => {
this.setState((prevState) => { const id = setInterval(rerender, 200);
return { return () => clearInterval(id);
rerenderFlag: !prevState.rerenderFlag, }, []);
};
});
}
render(): React.ReactNode {
return ( return (
<div className="stock-market-container"> <div className="stock-market-container">
<InfoAndPurchases initStockMarket={this.props.initStockMarket} p={this.props.p} rerender={this.rerender} /> <InfoAndPurchases initStockMarket={props.initStockMarket} p={props.p} rerender={rerender} />
{this.props.p.hasWseAccount && ( {props.p.hasWseAccount && (
<StockTickers <StockTickers
buyStockLong={this.props.buyStockLong} buyStockLong={props.buyStockLong}
buyStockShort={this.props.buyStockShort} buyStockShort={props.buyStockShort}
cancelOrder={this.props.cancelOrder} cancelOrder={props.cancelOrder}
eventEmitterForReset={this.props.eventEmitterForReset} eventEmitterForReset={props.eventEmitterForReset}
p={this.props.p} p={props.p}
placeOrder={this.props.placeOrder} placeOrder={props.placeOrder}
sellStockLong={this.props.sellStockLong} sellStockLong={props.sellStockLong}
sellStockShort={this.props.sellStockShort} sellStockShort={props.sellStockShort}
stockMarket={this.props.stockMarket} stockMarket={props.stockMarket}
/> />
)} )}
</div> </div>
); );
} }
}

@ -53,7 +53,7 @@ import { initForeignServers, AllServers } from "./Server/AllServers";
import { Settings } from "./Settings/Settings"; import { Settings } from "./Settings/Settings";
import { updateSourceFileFlags } from "./SourceFile/SourceFileFlags"; import { updateSourceFileFlags } from "./SourceFile/SourceFileFlags";
import { initSpecialServerIps } from "./Server/SpecialServerIps"; import { initSpecialServerIps } from "./Server/SpecialServerIps";
import { initSymbolToStockMap, processStockPrices, displayStockMarketContent } from "./StockMarket/StockMarket"; import { initSymbolToStockMap, processStockPrices } from "./StockMarket/StockMarket";
import { MilestonesRoot } from "./Milestones/ui/MilestonesRoot"; import { MilestonesRoot } from "./Milestones/ui/MilestonesRoot";
import { TerminalRoot } from "./Terminal/ui/TerminalRoot"; import { TerminalRoot } from "./Terminal/ui/TerminalRoot";
import { Terminal } from "./Terminal"; import { Terminal } from "./Terminal";
@ -308,7 +308,7 @@ const Engine = {
Engine.Display.content.style.display = "block"; Engine.Display.content.style.display = "block";
routing.navigateTo(Page.StockMarket); routing.navigateTo(Page.StockMarket);
MainMenuLinks.StockMarket.classList.add("active"); MainMenuLinks.StockMarket.classList.add("active");
displayStockMarketContent(); //displayStockMarketContent();
}, },
loadGangContent: function () { loadGangContent: function () {

@ -12,6 +12,14 @@ import { Faction } from "../Faction/Faction";
import { prestigeAugmentation } from "../Prestige"; import { prestigeAugmentation } from "../Prestige";
import { dialogBoxCreate } from "../../utils/DialogBox"; import { dialogBoxCreate } from "../../utils/DialogBox";
import { AllServers } from "../Server/AllServers"; import { AllServers } from "../Server/AllServers";
import { buyStock, sellStock, shortStock, sellShort } from "../StockMarket/BuyingAndSelling";
import {
cancelOrder,
eventEmitterForUiReset,
initStockMarketFnForReact,
placeOrder,
StockMarket,
} from "../StockMarket/StockMarket";
import { Theme } from "@mui/material/styles"; import { Theme } from "@mui/material/styles";
import makeStyles from "@mui/styles/makeStyles"; import makeStyles from "@mui/styles/makeStyles";
@ -41,7 +49,7 @@ import { FactionsRoot } from "../Faction/ui/FactionsRoot";
import { FactionRoot } from "../Faction/ui/FactionRoot"; import { FactionRoot } from "../Faction/ui/FactionRoot";
import { CharacterInfo } from "./CharacterInfo"; import { CharacterInfo } from "./CharacterInfo";
import { TravelAgencyRoot } from "../Locations/ui/TravelAgencyRoot"; import { TravelAgencyRoot } from "../Locations/ui/TravelAgencyRoot";
import { StockMarketRoot } from "../Locations/ui/StockMarketRoot"; import { StockMarketRoot } from "../StockMarket/ui/StockMarketRoot";
import { workerScripts } from "../Netscript/WorkerScripts"; import { workerScripts } from "../Netscript/WorkerScripts";
import { startHackingMission } from "../Faction/FactionHelpers"; import { startHackingMission } from "../Faction/FactionHelpers";
@ -90,7 +98,10 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
toStockMarket: () => setPage(Page.StockMarket), toStockMarket: () => setPage(Page.StockMarket),
toTerminal: () => setPage(Page.Terminal), toTerminal: () => setPage(Page.Terminal),
toTutorial: () => setPage(Page.Tutorial), toTutorial: () => setPage(Page.Tutorial),
toJob: () => setPage(Page.Job), toJob: () => {
player.gotoLocation(player.companyName as LocationName);
setPage(Page.Job);
},
toCity: () => { toCity: () => {
// TODO This is bad. // TODO This is bad.
player.gotoLocation(player.city as unknown as LocationName); player.gotoLocation(player.city as unknown as LocationName);
@ -141,8 +152,6 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
<ResleeveRoot player={player} /> <ResleeveRoot player={player} />
) : page === Page.Travel ? ( ) : page === Page.Travel ? (
<TravelAgencyRoot p={player} router={router} /> <TravelAgencyRoot p={player} router={router} />
) : page === Page.City ? (
<LocationRoot initiallyInCity={true} engine={engine} p={player} router={router} />
) : page === Page.StockMarket ? ( ) : page === Page.StockMarket ? (
<StockMarketRoot <StockMarketRoot
buyStockLong={buyStock} buyStockLong={buyStock}
@ -150,12 +159,16 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
cancelOrder={cancelOrder} cancelOrder={cancelOrder}
eventEmitterForReset={eventEmitterForUiReset} eventEmitterForReset={eventEmitterForUiReset}
initStockMarket={initStockMarketFnForReact} initStockMarket={initStockMarketFnForReact}
p={Player} p={player}
placeOrder={placeOrder} placeOrder={placeOrder}
sellStockLong={sellStock} sellStockLong={sellStock}
sellStockShort={sellShort} sellStockShort={sellShort}
stockMarket={castedStockMarket} stockMarket={StockMarket}
/> />
) : page === Page.City ? (
<LocationRoot initiallyInCity={true} engine={engine} p={player} router={router} />
) : page === Page.Job ? (
<LocationRoot initiallyInCity={false} engine={engine} p={player} router={router} />
) : page === Page.Options ? ( ) : page === Page.Options ? (
<GameOptionsRoot <GameOptionsRoot
player={player} player={player}

@ -1141,7 +1141,6 @@ describe("Stock Market Tests", function () {
Player.setMoney(100e9); Player.setMoney(100e9);
processOrdersRefs = { processOrdersRefs = {
rerenderFn: () => undefined,
stockMarket: StockMarket as IStockMarket, stockMarket: StockMarket as IStockMarket,
symbolToStockMap: SymbolToStockMap, symbolToStockMap: SymbolToStockMap,
}; };