mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-11 18:23:54 +01:00
189 lines
6.1 KiB
TypeScript
189 lines
6.1 KiB
TypeScript
/**
|
|
* React Component for the Stock Market UI. This is the container for all
|
|
* of the stock tickers. It also contains the configuration for the
|
|
* stock ticker UI (watchlist filter, portfolio vs all mode, etc.)
|
|
*/
|
|
import * as React from "react";
|
|
|
|
import { StockTicker } from "./StockTicker";
|
|
import { StockTickersConfig, TickerDisplayMode } from "./StockTickersConfig";
|
|
|
|
import { IStockMarket } from "../IStockMarket";
|
|
import { Stock } from "../Stock";
|
|
import { OrderTypes } from "../data/OrderTypes";
|
|
import { PositionTypes } from "../data/PositionTypes";
|
|
|
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
|
|
|
export type txFn = (stock: Stock, shares: number) => boolean;
|
|
export type placeOrderFn = (stock: Stock, shares: number, price: number, ordType: OrderTypes, posType: PositionTypes) => boolean;
|
|
|
|
type IProps = {
|
|
buyStockLong: txFn;
|
|
buyStockShort: txFn;
|
|
cancelOrder: (params: object) => void;
|
|
p: IPlayer;
|
|
placeOrder: placeOrderFn;
|
|
sellStockLong: txFn;
|
|
sellStockShort: txFn;
|
|
stockMarket: IStockMarket;
|
|
}
|
|
|
|
type IState = {
|
|
rerenderFlag: boolean;
|
|
tickerDisplayMode: TickerDisplayMode;
|
|
watchlistFilter: string;
|
|
watchlistSymbols: string[];
|
|
}
|
|
|
|
export class StockTickers extends React.Component<IProps, IState> {
|
|
listRef: React.RefObject<HTMLUListElement>;
|
|
|
|
constructor(props: IProps) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
rerenderFlag: false,
|
|
tickerDisplayMode: TickerDisplayMode.AllStocks,
|
|
watchlistFilter: "",
|
|
watchlistSymbols: [],
|
|
}
|
|
|
|
this.changeDisplayMode = this.changeDisplayMode.bind(this);
|
|
this.changeWatchlistFilter = this.changeWatchlistFilter.bind(this);
|
|
this.collapseAllTickers = this.collapseAllTickers.bind(this);
|
|
this.expandAllTickers = this.expandAllTickers.bind(this);
|
|
this.rerender = this.rerender.bind(this);
|
|
|
|
this.listRef = React.createRef();
|
|
}
|
|
|
|
changeDisplayMode() {
|
|
if (this.state.tickerDisplayMode === TickerDisplayMode.AllStocks) {
|
|
this.setState({
|
|
tickerDisplayMode: TickerDisplayMode.Portfolio,
|
|
});
|
|
} else {
|
|
this.setState({
|
|
tickerDisplayMode: TickerDisplayMode.AllStocks,
|
|
});
|
|
}
|
|
}
|
|
|
|
changeWatchlistFilter(e: React.ChangeEvent<HTMLInputElement>) {
|
|
const watchlist = e.target.value;
|
|
const sanitizedWatchlist = watchlist.replace(/\s/g, '');
|
|
|
|
this.setState({
|
|
watchlistFilter: watchlist,
|
|
});
|
|
|
|
if (sanitizedWatchlist !== "") {
|
|
this.setState({
|
|
watchlistSymbols: sanitizedWatchlist.split(","),
|
|
});
|
|
} else {
|
|
this.setState({
|
|
watchlistSymbols: [],
|
|
});
|
|
}
|
|
}
|
|
|
|
collapseAllTickers() {
|
|
const ul = this.listRef.current;
|
|
if (ul == null) { return; }
|
|
const tickers = ul.getElementsByClassName("accordion-header");
|
|
for (let i = 0; i < tickers.length; ++i) {
|
|
const ticker = tickers[i];
|
|
if (!(ticker instanceof HTMLButtonElement)) {
|
|
continue;
|
|
}
|
|
|
|
if (ticker.classList.contains("active")) {
|
|
ticker.click();
|
|
}
|
|
}
|
|
}
|
|
|
|
expandAllTickers() {
|
|
const ul = this.listRef.current;
|
|
if (ul == null) { return; }
|
|
const tickers = ul.getElementsByClassName("accordion-header");
|
|
for (let i = 0; i < tickers.length; ++i) {
|
|
const ticker = tickers[i];
|
|
if (!(ticker instanceof HTMLButtonElement)) {
|
|
continue;
|
|
}
|
|
|
|
if (!ticker.classList.contains("active")) {
|
|
ticker.click();
|
|
}
|
|
}
|
|
}
|
|
|
|
rerender() {
|
|
this.setState((prevState) => {
|
|
return {
|
|
rerenderFlag: !prevState.rerenderFlag,
|
|
}
|
|
});
|
|
}
|
|
|
|
render() {
|
|
const tickers: React.ReactElement[] = [];
|
|
for (const stockMarketProp in this.props.stockMarket) {
|
|
const val = this.props.stockMarket[stockMarketProp];
|
|
if (val instanceof Stock) {
|
|
// Skip if there's a filter and the stock isnt in that filter
|
|
if (this.state.watchlistSymbols.length > 0 && !this.state.watchlistSymbols.includes(val.symbol)) {
|
|
continue;
|
|
}
|
|
|
|
let orders = this.props.stockMarket.Orders[val.symbol];
|
|
if (orders == null) {
|
|
orders = [];
|
|
}
|
|
|
|
// Skip if we're in portfolio mode and the player doesnt own this or have any active orders
|
|
if (this.state.tickerDisplayMode === TickerDisplayMode.Portfolio) {
|
|
if (val.playerShares === 0 && val.playerShortShares === 0 && orders.length === 0) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
tickers.push(
|
|
<StockTicker
|
|
buyStockLong={this.props.buyStockLong}
|
|
buyStockShort={this.props.buyStockShort}
|
|
cancelOrder={this.props.cancelOrder}
|
|
key={val.symbol}
|
|
orders={orders}
|
|
p={this.props.p}
|
|
placeOrder={this.props.placeOrder}
|
|
rerenderAllTickers={this.rerender}
|
|
sellStockLong={this.props.sellStockLong}
|
|
sellStockShort={this.props.sellStockShort}
|
|
stock={val}
|
|
/>
|
|
)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<StockTickersConfig
|
|
changeDisplayMode={this.changeDisplayMode}
|
|
changeWatchlistFilter={this.changeWatchlistFilter}
|
|
collapseAllTickers={this.collapseAllTickers}
|
|
expandAllTickers={this.expandAllTickers}
|
|
tickerDisplayMode={this.state.tickerDisplayMode}
|
|
/>
|
|
|
|
<ul id="stock-market-list" ref={this.listRef}>
|
|
{tickers}
|
|
</ul>
|
|
</div>
|
|
)
|
|
}
|
|
}
|