mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 20:25:45 +01:00
Resolved more circular dependencies. Installed acorn-walk and imported it in RamCalculations using ES6 modules. Fixed bugs in stock market rework
This commit is contained in:
parent
8a5b6f6cbc
commit
cdb5dfec62
11
package-lock.json
generated
11
package-lock.json
generated
@ -671,9 +671,9 @@
|
||||
}
|
||||
},
|
||||
"acorn": {
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz",
|
||||
"integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ=="
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
|
||||
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw=="
|
||||
},
|
||||
"acorn-dynamic-import": {
|
||||
"version": "2.0.2",
|
||||
@ -707,6 +707,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"acorn-walk": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz",
|
||||
"integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw=="
|
||||
},
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
|
@ -9,8 +9,9 @@
|
||||
"@types/numeral": "0.0.25",
|
||||
"@types/react": "^16.8.6",
|
||||
"@types/react-dom": "^16.8.2",
|
||||
"acorn": "^5.0.0",
|
||||
"acorn": "^5.7.3",
|
||||
"acorn-dynamic-import": "^2.0.0",
|
||||
"acorn-walk": "^6.1.1",
|
||||
"ajv": "^5.1.5",
|
||||
"ajv-keywords": "^2.0.0",
|
||||
"async": "^2.6.1",
|
||||
|
@ -61,7 +61,7 @@ export function purchaseHacknet() {
|
||||
}
|
||||
}
|
||||
/* END INTERACTIVE TUTORIAL */
|
||||
|
||||
|
||||
const numOwned = Player.hacknetNodes.length;
|
||||
if (hasHacknetServers()) {
|
||||
const cost = getCostOfNextHacknetServer();
|
||||
|
@ -9,7 +9,6 @@ import { IHacknetNode } from "./IHacknetNode";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
import { Generic_fromJSON,
|
||||
|
@ -39,6 +39,8 @@ export class HacknetRoot extends React.Component {
|
||||
}
|
||||
|
||||
this.createHashUpgradesPopup = this.createHashUpgradesPopup.bind(this);
|
||||
this.handlePurchaseButtonClick = this.handlePurchaseButtonClick.bind(this);
|
||||
this.recalculateTotalProduction = this.recalculateTotalProduction.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -50,6 +52,12 @@ export class HacknetRoot extends React.Component {
|
||||
createPopup(id, HashUpgradePopup, { popupId: id, rerender: this.createHashUpgradesPopup });
|
||||
}
|
||||
|
||||
handlePurchaseButtonClick() {
|
||||
if (purchaseHacknet() >= 0) {
|
||||
this.recalculateTotalProduction();
|
||||
}
|
||||
}
|
||||
|
||||
recalculateTotalProduction() {
|
||||
let total = 0;
|
||||
for (let i = 0; i < Player.hacknetNodes.length; ++i) {
|
||||
@ -85,13 +93,6 @@ export class HacknetRoot extends React.Component {
|
||||
purchaseCost = getCostOfNextHacknetNode();
|
||||
}
|
||||
|
||||
// onClick event handler for purchase button
|
||||
const purchaseOnClick = () => {
|
||||
if (purchaseHacknet() >= 0) {
|
||||
this.recalculateTotalProduction();
|
||||
}
|
||||
}
|
||||
|
||||
// onClick event handlers for purchase multiplier buttons
|
||||
const purchaseMultiplierOnClicks = [
|
||||
this.setPurchaseMultiplier.bind(this, PurchaseMultipliers.x1),
|
||||
@ -112,7 +113,7 @@ export class HacknetRoot extends React.Component {
|
||||
key={hserver.hostname}
|
||||
node={hserver}
|
||||
purchaseMultiplier={this.state.purchaseMultiplier}
|
||||
recalculate={this.recalculateTotalProduction.bind(this)}
|
||||
recalculate={this.recalculateTotalProduction}
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
@ -121,7 +122,7 @@ export class HacknetRoot extends React.Component {
|
||||
key={node.name}
|
||||
node={node}
|
||||
purchaseMultiplier={this.state.purchaseMultiplier}
|
||||
recalculate={this.recalculateTotalProduction.bind(this)}
|
||||
recalculate={this.recalculateTotalProduction}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@ -132,7 +133,7 @@ export class HacknetRoot extends React.Component {
|
||||
<h1>Hacknet Nodes</h1>
|
||||
<GeneralInfo />
|
||||
|
||||
<PurchaseButton cost={purchaseCost} multiplier={this.state.purchaseMultiplier} onClick={purchaseOnClick} />
|
||||
<PurchaseButton cost={purchaseCost} multiplier={this.state.purchaseMultiplier} onClick={this.handlePurchaseButtonClick} />
|
||||
|
||||
<br />
|
||||
<div id={"hacknet-nodes-money-multipliers-div"}>
|
||||
|
@ -321,7 +321,7 @@ function iTutorialEvaluateStep() {
|
||||
Engine.loadActiveScriptsContent();
|
||||
iTutorialSetText("This page displays stats/information about all of your scripts that are " +
|
||||
"running across every existing server. You can use this to gauge how well " +
|
||||
"your scripts are doing. Let's go back to the Terminal now using the 'Terminal'" +
|
||||
"your scripts are doing. Let's go back to the Terminal now using the 'Terminal' " +
|
||||
"link.");
|
||||
nextBtn.style.display = "none";
|
||||
|
||||
|
@ -1145,8 +1145,7 @@ function NetscriptFunctions(workerScript) {
|
||||
}
|
||||
|
||||
// Create new script if it does not already exist
|
||||
var newScript = new Script();
|
||||
newScript.filename = scriptname;
|
||||
var newScript = new Script(scriptname);
|
||||
newScript.code = sourceScript.code;
|
||||
newScript.ramUsage = sourceScript.ramUsage;
|
||||
newScript.server = destServer.ip;
|
||||
@ -1932,12 +1931,12 @@ function NetscriptFunctions(workerScript) {
|
||||
let script = workerScript.getScriptOnServer(fn);
|
||||
if (script == null) {
|
||||
// Create a new script
|
||||
script = new Script(fn, data, server.ip);
|
||||
script = new Script(fn, data, server.ip, server.scripts);
|
||||
server.scripts.push(script);
|
||||
return true;
|
||||
}
|
||||
mode === "w" ? script.code = data : script.code += data;
|
||||
script.updateRamUsage();
|
||||
script.updateRamUsage(server.scripts);
|
||||
} else {
|
||||
// Write to text file
|
||||
let txtFile = getTextFile(fn, server);
|
||||
|
@ -20,6 +20,8 @@ import {
|
||||
import { NetscriptFunctions } from "./NetscriptFunctions";
|
||||
import { executeJSScript } from "./NetscriptJSEvaluator";
|
||||
import { NetscriptPort } from "./NetscriptPort";
|
||||
import { Player } from "./Player";
|
||||
import { RunningScript } from "./Script/RunningScript";
|
||||
import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers";
|
||||
import {
|
||||
findRunningScript,
|
||||
|
@ -18,8 +18,8 @@ import {
|
||||
processHacknetEarnings
|
||||
} from "./Hacknet/HacknetHelpers";
|
||||
import { loadMessages, initMessages, Messages } from "./Message/MessageHelpers";
|
||||
import { loadAllRunningScripts } from "./NetscriptWorker";
|
||||
import { Player, loadPlayer } from "./Player";
|
||||
import { loadAllRunningScripts } from "./Script/ScriptHelpers";
|
||||
import { AllServers, loadAllServers } from "./Server/AllServers";
|
||||
import { Settings } from "./Settings/Settings";
|
||||
import {
|
||||
|
4
src/Script/RamCalculations.d.ts
vendored
4
src/Script/RamCalculations.d.ts
vendored
@ -1 +1,3 @@
|
||||
export declare function calculateRamUsage(codeCopy: string): number;
|
||||
import { Script } from "./Script";
|
||||
|
||||
export declare function calculateRamUsage(codeCopy: string, otherScripts: Script[]): number;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Calculate a script's RAM usage
|
||||
const walk = require("acorn/dist/walk"); // Importing this doesn't work for some reason.
|
||||
import * as walk from "acorn-walk";
|
||||
|
||||
import { RamCosts, RamCostConstants } from "../Netscript/RamCostGenerator";
|
||||
import { parse, Node } from "../../utils/acorn";
|
||||
@ -16,7 +16,7 @@ const memCheckGlobalKey = ".__GLOBAL__";
|
||||
// Calcluates the amount of RAM a script uses. Uses parsing and AST walking only,
|
||||
// rather than NetscriptEvaluator. This is useful because NetscriptJS code does
|
||||
// not work under NetscriptEvaluator.
|
||||
async function parseOnlyRamCalculate(server, code, workerScript) {
|
||||
async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
|
||||
try {
|
||||
// Maps dependent identifiers to their dependencies.
|
||||
//
|
||||
@ -74,11 +74,25 @@ async function parseOnlyRamCalculate(server, code, workerScript) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
const script = server.getScript(nextModule.startsWith("./") ? nextModule.slice(2) : nextModule);
|
||||
if (!script) {
|
||||
if (!Array.isArray(otherScripts)) {
|
||||
console.warn(`parseOnlyRamCalculate() not called with array of scripts`);
|
||||
return -1;
|
||||
}
|
||||
|
||||
let script = null;
|
||||
let fn = nextModule.startsWith("./") ? nextModule.slice(2) : nextModule;
|
||||
for (const s of otherScripts) {
|
||||
if (s.filename === fn) {
|
||||
script = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (script == null) {
|
||||
console.warn("Invalid script");
|
||||
return -1; // No such script on the server.
|
||||
}
|
||||
|
||||
code = script.code;
|
||||
}
|
||||
|
||||
@ -251,36 +265,6 @@ function parseOnlyCalculateDeps(code, currentModule) {
|
||||
}
|
||||
}
|
||||
|
||||
//Spread syntax not supported in Edge yet, use Object.assign
|
||||
/*
|
||||
walk.recursive(ast, {key: globalKey}, {
|
||||
ImportDeclaration: (node, st, walkDeeper) => {
|
||||
const importModuleName = node.source.value;
|
||||
additionalModules.push(importModuleName);
|
||||
|
||||
// This module's global scope refers to that module's global scope, no matter how we
|
||||
// import it.
|
||||
dependencyMap[st.key].add(importModuleName + memCheckGlobalKey);
|
||||
|
||||
for (let i = 0; i < node.specifiers.length; ++i) {
|
||||
const spec = node.specifiers[i];
|
||||
if (spec.imported !== undefined && spec.local !== undefined) {
|
||||
// We depend on specific things.
|
||||
internalToExternal[spec.local.name] = importModuleName + "." + spec.imported.name;
|
||||
} else {
|
||||
// We depend on everything.
|
||||
dependencyMap[st.key].add(importModuleName + ".*");
|
||||
}
|
||||
}
|
||||
},
|
||||
FunctionDeclaration: (node, st, walkDeeper) => {
|
||||
// Don't use walkDeeper, because we are changing the visitor set.
|
||||
const key = currentModule + "." + node.id.name;
|
||||
walk.recursive(node, {key: key}, commonVisitors());
|
||||
},
|
||||
...commonVisitors()
|
||||
});
|
||||
*/
|
||||
walk.recursive(ast, {key: globalKey}, Object.assign({
|
||||
ImportDeclaration: (node, st, walkDeeper) => {
|
||||
const importModuleName = node.source.value;
|
||||
@ -311,19 +295,18 @@ function parseOnlyCalculateDeps(code, currentModule) {
|
||||
return {dependencyMap: dependencyMap, additionalModules: additionalModules};
|
||||
}
|
||||
|
||||
export async function calculateRamUsage(codeCopy) {
|
||||
export async function calculateRamUsage(codeCopy, otherScripts) {
|
||||
// We don't need a real WorkerScript for this. Just an object that keeps
|
||||
// track of whatever's needed for RAM calculations
|
||||
const workerScript = {
|
||||
loadedFns: {},
|
||||
serverIp: currServ.ip,
|
||||
env: {
|
||||
vars: RamCosts,
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return await parseOnlyRamCalculate(currServ, codeCopy, workerScript);
|
||||
return await parseOnlyRamCalculate(otherScripts, codeCopy, workerScript);
|
||||
} catch (e) {
|
||||
console.error(`Failed to parse script for RAM calculations:`);
|
||||
console.error(e);
|
||||
|
@ -35,13 +35,13 @@ export class Script {
|
||||
server: string = "";
|
||||
|
||||
|
||||
constructor(fn: string = "", code: string = "", server: string = "") {
|
||||
constructor(fn: string="", code: string="", server: string="", otherScripts: Script[]=[]) {
|
||||
this.filename = fn;
|
||||
this.code = code;
|
||||
this.ramUsage = 0;
|
||||
this.server = server; // IP of server this script is on
|
||||
this.module = "";
|
||||
if (this.code !== "") {this.updateRamUsage();}
|
||||
if (this.code !== "") { this.updateRamUsage(otherScripts); }
|
||||
};
|
||||
|
||||
download(): void {
|
||||
@ -64,7 +64,7 @@ export class Script {
|
||||
}
|
||||
|
||||
// Save a script FROM THE SCRIPT EDITOR
|
||||
saveScript(code: string, currServ: string): void {
|
||||
saveScript(code: string, serverIp: string, otherScripts: Script[]): void {
|
||||
if (routing.isOn(Page.ScriptEditor)) {
|
||||
//Update code and filename
|
||||
this.code = code.replace(/^\s+|\s+$/g, '');
|
||||
@ -77,21 +77,18 @@ export class Script {
|
||||
this.filename = filenameElem!.value;
|
||||
|
||||
// Server
|
||||
this.server = currServ;
|
||||
this.server = serverIp;
|
||||
|
||||
//Calculate/update ram usage, execution time, etc.
|
||||
this.updateRamUsage();
|
||||
this.updateRamUsage(otherScripts);
|
||||
|
||||
this.module = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the script's RAM usage based on its code
|
||||
async updateRamUsage() {
|
||||
// TODO Commented this out because I think its unnecessary
|
||||
// DOuble check/Test
|
||||
// var codeCopy = this.code.repeat(1);
|
||||
var res = await calculateRamUsage(this.code);
|
||||
async updateRamUsage(otherScripts: Script[]) {
|
||||
var res = await calculateRamUsage(this.code, otherScripts);
|
||||
if (res !== -1) {
|
||||
this.ramUsage = roundToTwo(res);
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ export async function updateScriptEditorContent() {
|
||||
}
|
||||
|
||||
var codeCopy = code.repeat(1);
|
||||
var ramUsage = await calculateRamUsage(codeCopy);
|
||||
var ramUsage = await calculateRamUsage(codeCopy, Player.getCurrentServer().scripts);
|
||||
if (ramUsage !== -1) {
|
||||
scriptEditorRamText.innerText = "RAM: " + numeralWrapper.format(ramUsage, '0.00') + " GB";
|
||||
} else {
|
||||
@ -236,15 +236,15 @@ function saveAndCloseScriptEditor() {
|
||||
let s = Player.getCurrentServer();
|
||||
for (var i = 0; i < s.scripts.length; i++) {
|
||||
if (filename == s.scripts[i].filename) {
|
||||
s.scripts[i].saveScript(getCurrentEditor().getCode(), Player.currentServer);
|
||||
s.scripts[i].saveScript(getCurrentEditor().getCode(), Player.currentServer, Player.getCurrentServer().scripts);
|
||||
Engine.loadTerminalContent();
|
||||
return iTutorialNextStep();
|
||||
}
|
||||
}
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
// If the current script does NOT exist, create a new one
|
||||
let script = new Script();
|
||||
script.saveScript(getCurrentEditor().getCode(), Player.currentServer);
|
||||
script.saveScript(getCurrentEditor().getCode(), Player.currentServer, Player.getCurrentServer().scripts);
|
||||
s.scripts.push(script);
|
||||
|
||||
return iTutorialNextStep();
|
||||
@ -272,7 +272,7 @@ function saveAndCloseScriptEditor() {
|
||||
//If the current script already exists on the server, overwrite it
|
||||
for (var i = 0; i < s.scripts.length; i++) {
|
||||
if (filename == s.scripts[i].filename) {
|
||||
s.scripts[i].saveScript(getCurrentEditor().getCode(), Player.currentServer);
|
||||
s.scripts[i].saveScript(getCurrentEditor().getCode(), Player.currentServer, Player.getCurrentServer().scripts);
|
||||
Engine.loadTerminalContent();
|
||||
return;
|
||||
}
|
||||
@ -280,7 +280,7 @@ function saveAndCloseScriptEditor() {
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
const script = new Script();
|
||||
script.saveScript(getCurrentEditor().getCode(), Player.currentServer);
|
||||
script.saveScript(getCurrentEditor().getCode(), Player.currentServer, Player.getCurrentServer().scripts);
|
||||
s.scripts.push(script);
|
||||
} else if (filename.endsWith(".txt")) {
|
||||
for (var i = 0; i < s.textFiles.length; ++i) {
|
||||
|
@ -231,7 +231,7 @@ export class BaseServer {
|
||||
if (fn === this.scripts[i].filename) {
|
||||
let script = this.scripts[i];
|
||||
script.code = code;
|
||||
script.updateRamUsage();
|
||||
script.updateRamUsage(this.scripts);
|
||||
script.module = "";
|
||||
ret.overwritten = true;
|
||||
ret.success = true;
|
||||
@ -240,11 +240,7 @@ export class BaseServer {
|
||||
}
|
||||
|
||||
//Otherwise, create a new script
|
||||
const newScript = new Script();
|
||||
newScript.filename = fn;
|
||||
newScript.code = code;
|
||||
newScript.updateRamUsage();
|
||||
newScript.server = this.ip;
|
||||
const newScript = new Script(fn, code, this.ip, this.scripts);
|
||||
this.scripts.push(newScript);
|
||||
ret.success = true;
|
||||
return ret;
|
||||
|
@ -107,7 +107,7 @@ export function prestigeHomeComputer(homeComp: Server) {
|
||||
|
||||
//Update RAM usage on all scripts
|
||||
homeComp.scripts.forEach(function(script) {
|
||||
script.updateRamUsage();
|
||||
script.updateRamUsage(homeComp.scripts);
|
||||
});
|
||||
|
||||
homeComp.messages.length = 0; //Remove .lit and .msg files
|
||||
|
@ -41,11 +41,11 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip
|
||||
|
||||
// Validate arguments
|
||||
shares = Math.round(shares);
|
||||
if (shares == 0 || shares < 0) { return false; }
|
||||
if (shares <= 0) { return false; }
|
||||
if (stock == null || isNaN(shares)) {
|
||||
if (tixApi) {
|
||||
workerScript!.log(`ERROR: buyStock() failed due to invalid arguments`);
|
||||
} else if (opts.suppressDialog != null && !opts.suppressDialog) {
|
||||
} else if (opts.suppressDialog !== true) {
|
||||
dialogBoxCreate("Failed to buy stock. This may be a bug, contact developer");
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip
|
||||
if (Player.money.lt(totalPrice)) {
|
||||
if (tixApi) {
|
||||
workerScript!.log(`ERROR: buyStock() failed because you do not have enough money to purchase this potiion. You need ${numeralWrapper.formatMoney(totalPrice)}`);
|
||||
} else if (opts.suppressDialog != null && !opts.suppressDialog) {
|
||||
} else if (opts.suppressDialog !== true) {
|
||||
dialogBoxCreate(`You do not have enough money to purchase this. You need ${numeralWrapper.formatMoney(totalPrice)}`);
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip
|
||||
if (shares + stock.playerShares + stock.playerShortShares > stock.maxShares) {
|
||||
if (tixApi) {
|
||||
workerScript!.log(`ERROR: buyStock() failed because purchasing this many shares would exceed ${stock.symbol}'s maximum number of shares`);
|
||||
} else if (opts.suppressDialog != null && !opts.suppressDialog) {
|
||||
} else if (opts.suppressDialog !== true) {
|
||||
dialogBoxCreate(`You cannot purchase this many shares. ${stock.symbol} has a maximum of ${numeralWrapper.formatBigNumber(stock.maxShares)} shares.`);
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ export function buyStock(stock: Stock, shares: number, workerScript: WorkerScrip
|
||||
`Paid ${numeralWrapper.formatMoney(CONSTANTS.StockMarketCommission)} in commission fees.`
|
||||
if (tixApi) {
|
||||
if (workerScript!.shouldLog("buyStock")) { workerScript!.log(resultTxt); }
|
||||
} else if (opts.suppressDialog != null && !opts.suppressDialog) {
|
||||
} else if (opts.suppressDialog !== true) {
|
||||
dialogBoxCreate(resultTxt);
|
||||
}
|
||||
|
||||
@ -112,15 +112,15 @@ export function sellStock(stock: Stock, shares: number, workerScript: WorkerScri
|
||||
if (stock == null || shares < 0 || isNaN(shares)) {
|
||||
if (tixApi) {
|
||||
workerScript!.log(`ERROR: sellStock() failed due to invalid arguments`);
|
||||
} else if (opts.suppressDialog != null && !opts.suppressDialog) {
|
||||
} else if (opts.suppressDialog !== true) {
|
||||
dialogBoxCreate("Failed to sell stock. This is probably due to an invalid quantity. Otherwise, this may be a bug, contact developer");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
shares = Math.round(shares);
|
||||
if (shares > stock.playerShares) {shares = stock.playerShares;}
|
||||
if (shares === 0) {return false;}
|
||||
if (shares > stock.playerShares) { shares = stock.playerShares; }
|
||||
if (shares === 0) { return false; }
|
||||
|
||||
const gains = getSellTransactionGain(stock, shares, PositionTypes.Long);
|
||||
if (gains == null) { return false; }
|
||||
@ -148,7 +148,7 @@ export function sellStock(stock: Stock, shares: number, workerScript: WorkerScri
|
||||
`After commissions, you gained a total of ${numeralWrapper.formatMoney(gains)}.`;
|
||||
if (tixApi) {
|
||||
if (workerScript!.shouldLog("sellStock")) { workerScript!.log(resultTxt); }
|
||||
} else if (opts.suppressDialog != null && !opts.suppressDialog) {
|
||||
} else if (opts.suppressDialog !== true) {
|
||||
dialogBoxCreate(resultTxt);
|
||||
}
|
||||
|
||||
@ -168,11 +168,11 @@ export function shortStock(stock: Stock, shares: number, workerScript: WorkerScr
|
||||
|
||||
// Validate arguments
|
||||
shares = Math.round(shares);
|
||||
if (shares === 0 || shares < 0) { return false; }
|
||||
if (shares <= 0) { return false; }
|
||||
if (stock == null || isNaN(shares)) {
|
||||
if (tixApi) {
|
||||
workerScript!.log("ERROR: shortStock() failed because of invalid arguments.");
|
||||
} else if (opts.suppressDialog != null && !opts.suppressDialog) {
|
||||
} else if (opts.suppressDialog !== true) {
|
||||
dialogBoxCreate("Failed to initiate a short position in a stock. This is probably " +
|
||||
"due to an invalid quantity. Otherwise, this may be a bug, so contact developer");
|
||||
}
|
||||
@ -187,7 +187,7 @@ export function shortStock(stock: Stock, shares: number, workerScript: WorkerScr
|
||||
workerScript!.log("ERROR: shortStock() failed because you do not have enough " +
|
||||
"money to purchase this short position. You need " +
|
||||
numeralWrapper.formatMoney(totalPrice));
|
||||
} else if (opts.suppressDialog != null && !opts.suppressDialog) {
|
||||
} else if (opts.suppressDialog !== true) {
|
||||
dialogBoxCreate("You do not have enough money to purchase this short position. You need " +
|
||||
numeralWrapper.formatMoney(totalPrice));
|
||||
}
|
||||
@ -199,7 +199,7 @@ export function shortStock(stock: Stock, shares: number, workerScript: WorkerScr
|
||||
if (shares + stock.playerShares + stock.playerShortShares > stock.maxShares) {
|
||||
if (tixApi) {
|
||||
workerScript!.log(`ERROR: shortStock() failed because purchasing this many short shares would exceed ${stock.symbol}'s maximum number of shares.`);
|
||||
} else if (opts.suppressDialog != null && !opts.suppressDialog) {
|
||||
} else if (opts.suppressDialog !== true) {
|
||||
dialogBoxCreate(`You cannot purchase this many shares. ${stock.symbol} has a maximum of ${stock.maxShares} shares.`);
|
||||
}
|
||||
|
||||
|
@ -2,14 +2,13 @@
|
||||
* Represents a Limit or Buy Order on the stock market. Does not represent
|
||||
* a Market Order since those are just executed immediately
|
||||
*/
|
||||
import { Stock } from "./Stock";
|
||||
import { OrderTypes } from "./data/OrderTypes";
|
||||
import { PositionTypes } from "./data/PositionTypes";
|
||||
|
||||
import {
|
||||
Generic_fromJSON,
|
||||
Generic_toJSON,
|
||||
Reviver
|
||||
Reviver,
|
||||
} from "../../utils/JSONReviver";
|
||||
|
||||
export class Order {
|
||||
@ -23,10 +22,10 @@ export class Order {
|
||||
readonly pos: PositionTypes;
|
||||
readonly price: number;
|
||||
shares: number;
|
||||
readonly stock: Stock;
|
||||
readonly stockSymbol: string;
|
||||
readonly type: OrderTypes;
|
||||
|
||||
constructor(stk: Stock = new Stock(), shares: number=0, price: number=0, typ: OrderTypes=OrderTypes.LimitBuy, pos: PositionTypes=PositionTypes.Long) {
|
||||
constructor(stockSymbol: string="", shares: number=0, price: number=0, typ: OrderTypes=OrderTypes.LimitBuy, pos: PositionTypes=PositionTypes.Long) {
|
||||
// Validate arguments
|
||||
let invalidArgs: boolean = false;
|
||||
if (typeof shares !== "number" || typeof price !== "number") {
|
||||
@ -35,14 +34,14 @@ export class Order {
|
||||
if (isNaN(shares) || isNaN(price)) {
|
||||
invalidArgs = true;
|
||||
}
|
||||
if (!(stk instanceof Stock)) {
|
||||
if (typeof stockSymbol !== "string") {
|
||||
invalidArgs = true;
|
||||
}
|
||||
if (invalidArgs) {
|
||||
throw new Error(`Invalid constructor paramters for Order`);
|
||||
}
|
||||
|
||||
this.stock = stk;
|
||||
this.stockSymbol = stockSymbol;
|
||||
this.shares = shares;
|
||||
this.price = price;
|
||||
this.type = typ;
|
||||
|
@ -16,6 +16,8 @@ import { Stock } from "./Stock";
|
||||
import { OrderTypes } from "./data/OrderTypes";
|
||||
import { PositionTypes } from "./data/PositionTypes";
|
||||
|
||||
import { IMap } from "../types";
|
||||
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
@ -23,6 +25,7 @@ import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
interface IProcessOrderRefs {
|
||||
rerenderFn: () => void;
|
||||
stockMarket: IStockMarket;
|
||||
symbolToStockMap: IMap<Stock>;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -56,30 +59,30 @@ export function processOrders(stock: Stock, orderType: OrderTypes, posType: Posi
|
||||
switch (order.type) {
|
||||
case OrderTypes.LimitBuy:
|
||||
if (order.pos === PositionTypes.Long && stock.price <= order.price) {
|
||||
executeOrder/*66*/(order, refs.stockMarket, refs.rerenderFn);
|
||||
executeOrder/*66*/(order, refs);
|
||||
} else if (order.pos === PositionTypes.Short && stock.price >= order.price) {
|
||||
executeOrder/*66*/(order, refs.stockMarket, refs.rerenderFn);
|
||||
executeOrder/*66*/(order, refs);
|
||||
}
|
||||
break;
|
||||
case OrderTypes.LimitSell:
|
||||
if (order.pos === PositionTypes.Long && stock.price >= order.price) {
|
||||
executeOrder/*66*/(order, refs.stockMarket, refs.rerenderFn);
|
||||
executeOrder/*66*/(order, refs);
|
||||
} else if (order.pos === PositionTypes.Short && stock.price <= order.price) {
|
||||
executeOrder/*66*/(order, refs.stockMarket, refs.rerenderFn);
|
||||
executeOrder/*66*/(order, refs);
|
||||
}
|
||||
break;
|
||||
case OrderTypes.StopBuy:
|
||||
if (order.pos === PositionTypes.Long && stock.price >= order.price) {
|
||||
executeOrder/*66*/(order, refs.stockMarket, refs.rerenderFn);
|
||||
executeOrder/*66*/(order, refs);
|
||||
} else if (order.pos === PositionTypes.Short && stock.price <= order.price) {
|
||||
executeOrder/*66*/(order, refs.stockMarket, refs.rerenderFn);
|
||||
executeOrder/*66*/(order, refs);
|
||||
}
|
||||
break;
|
||||
case OrderTypes.StopSell:
|
||||
if (order.pos === PositionTypes.Long && stock.price <= order.price) {
|
||||
executeOrder/*66*/(order, refs.stockMarket, refs.rerenderFn);
|
||||
executeOrder/*66*/(order, refs);
|
||||
} else if (order.pos === PositionTypes.Short && stock.price >= order.price) {
|
||||
executeOrder/*66*/(order, refs.stockMarket, refs.rerenderFn);
|
||||
executeOrder/*66*/(order, refs);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -95,24 +98,27 @@ export function processOrders(stock: Stock, orderType: OrderTypes, posType: Posi
|
||||
* @param {Order} order - Order being executed
|
||||
* @param {IStockMarket} stockMarket - Reference to StockMarket object
|
||||
*/
|
||||
function executeOrder(order: Order, stockMarket: IStockMarket, rerenderFn: () => void) {
|
||||
const stock = order.stock;
|
||||
function executeOrder(order: Order, refs: IProcessOrderRefs) {
|
||||
const stock = refs.symbolToStockMap[order.stockSymbol];
|
||||
if (!(stock instanceof Stock)) {
|
||||
console.error(`Could not find stock for this order: ${order.stockSymbol}`);
|
||||
return;
|
||||
}
|
||||
const stockMarket = refs.stockMarket;
|
||||
const orderBook = stockMarket["Orders"];
|
||||
const stockOrders = orderBook[stock.symbol];
|
||||
const isLimit = (order.type === OrderTypes.LimitBuy || order.type === OrderTypes.LimitSell);
|
||||
let limitShares = 0;
|
||||
let sharesTransacted = 0;
|
||||
|
||||
// When orders are executed, the buying and selling functions shouldn't
|
||||
// emit popup dialog boxes. This options object configures the functions for that
|
||||
const opts = {
|
||||
rerenderFn: rerenderFn,
|
||||
rerenderFn: refs.rerenderFn,
|
||||
suppressDialog: true
|
||||
}
|
||||
|
||||
let res = true;
|
||||
let isBuy = false;
|
||||
console.log("Executing the following order:");
|
||||
console.log(order);
|
||||
switch (order.type) {
|
||||
case OrderTypes.LimitBuy: {
|
||||
isBuy = true;
|
||||
@ -122,8 +128,9 @@ function executeOrder(order: Order, stockMarket: IStockMarket, rerenderFn: () =>
|
||||
const firstShares = Math.min(order.shares, stock.shareTxUntilMovement);
|
||||
|
||||
// First transaction to trigger movement
|
||||
if (isLong ? buyStock(stock, firstShares, null, opts) : shortStock(stock, firstShares, null, opts)) {
|
||||
limitShares = firstShares;
|
||||
let res = (isLong ? buyStock(stock, firstShares, null, opts) : shortStock(stock, firstShares, null, opts));
|
||||
if (res) {
|
||||
sharesTransacted = firstShares;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -138,16 +145,19 @@ function executeOrder(order: Order, stockMarket: IStockMarket, rerenderFn: () =>
|
||||
}
|
||||
|
||||
const shares = Math.min(remainingShares, stock.shareTxForMovement);
|
||||
if (isLong ? buyStock(stock, shares, null, opts) : shortStock(stock, shares, null, opts)) {
|
||||
limitShares += shares;
|
||||
let res = (isLong ? buyStock(stock, shares, null, opts) : shortStock(stock, shares, null, opts));
|
||||
if (res) {
|
||||
sharesTransacted += shares;
|
||||
remainingShares -= shares;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OrderTypes.StopBuy: {
|
||||
isBuy = true;
|
||||
sharesTransacted = order.shares;
|
||||
if (order.pos === PositionTypes.Long) {
|
||||
res = buyStock(stock, order.shares, null, opts) && res;
|
||||
} else if (order.pos === PositionTypes.Short) {
|
||||
@ -156,18 +166,23 @@ function executeOrder(order: Order, stockMarket: IStockMarket, rerenderFn: () =>
|
||||
break;
|
||||
}
|
||||
case OrderTypes.LimitSell: {
|
||||
// TODO need to account for player's shares here
|
||||
// We only execute limit orders until the price fails to match the order condition
|
||||
const isLong = (order.pos === PositionTypes.Long);
|
||||
const firstShares = Math.min(order.shares, stock.shareTxUntilMovement);
|
||||
const totalShares = Math.min((isLong ? stock.playerShares : stock.playerShortShares), order.shares);
|
||||
if (totalShares === 0) {
|
||||
return; // Player has no shares
|
||||
}
|
||||
const firstShares = Math.min(totalShares, stock.shareTxUntilMovement);
|
||||
|
||||
// First transaction to trigger movement
|
||||
if (isLong ? sellStock(stock, firstShares, null, opts) : sellShort(stock, firstShares, null, opts)) {
|
||||
limitShares = firstShares;
|
||||
sharesTransacted = firstShares;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
let remainingShares = order.shares - firstShares;
|
||||
let remainingShares = totalShares - firstShares;
|
||||
let remainingIterations = Math.ceil(remainingShares / stock.shareTxForMovement);
|
||||
for (let i = 0; i < remainingIterations; ++i) {
|
||||
if (isLong && stock.price < order.price) {
|
||||
@ -178,18 +193,23 @@ function executeOrder(order: Order, stockMarket: IStockMarket, rerenderFn: () =>
|
||||
|
||||
const shares = Math.min(remainingShares, stock.shareTxForMovement);
|
||||
if (isLong ? sellStock(stock, shares, null, opts) : sellShort(stock, shares, null, opts)) {
|
||||
limitShares += shares;
|
||||
sharesTransacted += shares;
|
||||
remainingShares -= shares;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OrderTypes.StopSell: {
|
||||
if (order.pos === PositionTypes.Long) {
|
||||
res = sellStock(stock, order.shares, null, opts) && res;
|
||||
sharesTransacted = Math.min(stock.playerShares, order.shares);
|
||||
if (sharesTransacted <= 0) { return; }
|
||||
res = sellStock(stock, sharesTransacted, null, opts) && res;
|
||||
} else if (order.pos === PositionTypes.Short) {
|
||||
res = sellShort(stock, order.shares, null, opts) && res;
|
||||
sharesTransacted = Math.min(stock.playerShortShares, order.shares);
|
||||
if (sharesTransacted <= 0) { return; }
|
||||
res = sellShort(stock, sharesTransacted, null, opts) && res;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -198,42 +218,27 @@ function executeOrder(order: Order, stockMarket: IStockMarket, rerenderFn: () =>
|
||||
return;
|
||||
}
|
||||
|
||||
if (isLimit) {
|
||||
res = (sharesTransacted > 0);
|
||||
}
|
||||
|
||||
// Position type, for logging/message purposes
|
||||
const pos = order.pos === PositionTypes.Long ? "Long" : "Short";
|
||||
|
||||
if (res) {
|
||||
if (isLimit) {
|
||||
|
||||
} else {
|
||||
|
||||
for (let i = 0; i < stockOrders.length; ++i) {
|
||||
if (order == stockOrders[i]) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < stockOrders.length; ++i) {
|
||||
if (order == stockOrders[i]) {
|
||||
if (isLimit) {
|
||||
// Limit orders might only transact a certain # of shares, so we have the adjust the order qty.
|
||||
stockOrders[i].shares -= limitShares;
|
||||
if (stockOrders[i].shares <= 0) {
|
||||
stockOrders.splice(i, 1);
|
||||
dialogBoxCreate(`${order.type} for ${order.stock.symbol} @ ${numeralWrapper.formatMoney(order.price)} (${pos}) was filled ` +
|
||||
`(${Math.round(limitShares)} shares`);
|
||||
} else {
|
||||
dialogBoxCreate(`${order.type} for ${order.stock.symbol} @ ${numeralWrapper.formatMoney(order.price)} (${pos}) was partially filled ` +
|
||||
`(${Math.round(limitShares)} shares transacted, ${stockOrders[i].shares} shares remaining`);
|
||||
}
|
||||
} else {
|
||||
// Stop orders will transact everything, so they can be removed completely
|
||||
// Limit orders might only transact a certain # of shares, so we have the adjust the order qty.
|
||||
stockOrders[i].shares -= sharesTransacted;
|
||||
if (stockOrders[i].shares <= 0) {
|
||||
stockOrders.splice(i, 1);
|
||||
dialogBoxCreate(`${order.type} for ${order.stock.symbol} @ ${numeralWrapper.formatMoney(order.price)} (${pos}) was filled ` +
|
||||
`(${Math.round(order.shares)} shares transacted)`);
|
||||
dialogBoxCreate(`${order.type} for ${stock.symbol} @ ${numeralWrapper.formatMoney(order.price)} (${pos}) was filled ` +
|
||||
`(${numeralWrapper.formatBigNumber(Math.round(sharesTransacted))} share)`);
|
||||
} else {
|
||||
dialogBoxCreate(`${order.type} for ${stock.symbol} @ ${numeralWrapper.formatMoney(order.price)} (${pos}) was partially filled ` +
|
||||
`(${numeralWrapper.formatBigNumber(Math.round(sharesTransacted))} shares transacted, ${stockOrders[i].shares} shares remaining`);
|
||||
}
|
||||
|
||||
rerenderFn();
|
||||
refs.rerenderFn();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -242,11 +247,11 @@ function executeOrder(order: Order, stockMarket: IStockMarket, rerenderFn: () =>
|
||||
console.error(order);
|
||||
} else {
|
||||
if (isBuy) {
|
||||
dialogBoxCreate(`Failed to execute ${order.type} for ${order.stock.symbol} @ ${numeralWrapper.formatMoney(order.price)} (${pos}). ` +
|
||||
dialogBoxCreate(`Failed to execute ${order.type} for ${stock.symbol} @ ${numeralWrapper.formatMoney(order.price)} (${pos}). ` +
|
||||
`This is most likely because you do not have enough money or the order would exceed the stock's maximum number of shares`);
|
||||
} else {
|
||||
dialogBoxCreate(`Failed to execute ${order.type} for ${order.stock.symbol} @ ${numeralWrapper.formatMoney(order.price)} (${pos}). ` +
|
||||
`This is most likely a bug, please report to game developer with details.`);
|
||||
dialogBoxCreate(`Failed to execute ${order.type} for ${stock.symbol} @ ${numeralWrapper.formatMoney(order.price)} (${pos}). ` +
|
||||
`This may be a bug, please report to game developer with details.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,16 +41,24 @@ export let SymbolToStockMap = {}; // Maps symbol -> Stock object
|
||||
|
||||
export function placeOrder(stock, shares, price, type, position, workerScript=null) {
|
||||
const tixApi = (workerScript instanceof WorkerScript);
|
||||
if (!(stock instanceof Stock)) {
|
||||
if (tixApi) {
|
||||
workerScript.log(`ERROR: Invalid stock passed to placeOrder() function`);
|
||||
} else {
|
||||
dialogBoxCreate(`ERROR: Invalid stock passed to placeOrder() function`);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (typeof shares !== "number" || typeof price !== "number") {
|
||||
if (tixApi) {
|
||||
workerScript.scriptRef.log("ERROR: Invalid numeric value provided for either 'shares' or 'price' argument");
|
||||
workerScript.log("ERROR: Invalid numeric value provided for either 'shares' or 'price' argument");
|
||||
} else {
|
||||
dialogBoxCreate("ERROR: Invalid numeric value provided for either 'shares' or 'price' argument");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const order = new Order(stock, shares, price, type, position);
|
||||
const order = new Order(stock.symbol, shares, price, type, position);
|
||||
if (StockMarket["Orders"] == null) {
|
||||
const orders = {};
|
||||
for (const name in StockMarket) {
|
||||
@ -66,8 +74,9 @@ export function placeOrder(stock, shares, price, type, position, workerScript=nu
|
||||
const processOrderRefs = {
|
||||
rerenderFn: displayStockMarketContent,
|
||||
stockMarket: StockMarket,
|
||||
symbolToStockMap: SymbolToStockMap,
|
||||
}
|
||||
processOrders(order.stock, order.type, order.pos, processOrderRefs);
|
||||
processOrders(stock, order.type, order.pos, processOrderRefs);
|
||||
displayStockMarketContent();
|
||||
|
||||
return true;
|
||||
@ -78,9 +87,9 @@ export function cancelOrder(params, workerScript=null) {
|
||||
var tixApi = (workerScript instanceof WorkerScript);
|
||||
if (StockMarket["Orders"] == null) {return false;}
|
||||
if (params.order && params.order instanceof Order) {
|
||||
var order = params.order;
|
||||
const order = params.order;
|
||||
// An 'Order' object is passed in
|
||||
var stockOrders = StockMarket["Orders"][order.stock.symbol];
|
||||
var stockOrders = StockMarket["Orders"][order.stockSymbol];
|
||||
for (var i = 0; i < stockOrders.length; ++i) {
|
||||
if (order == stockOrders[i]) {
|
||||
stockOrders.splice(i, 1);
|
||||
@ -122,6 +131,24 @@ export function loadStockMarket(saveString) {
|
||||
StockMarket = {};
|
||||
} else {
|
||||
StockMarket = JSON.parse(saveString, Reviver);
|
||||
|
||||
// Backwards compatibility for v0.47.0
|
||||
const orderBook = StockMarket["Orders"];
|
||||
if (orderBook != null) {
|
||||
// For each order, set its 'stockSymbol' property equal to the
|
||||
// symbol of its 'stock' property
|
||||
for (const stockSymbol in orderBook) {
|
||||
const ordersForStock = orderBook[stockSymbol];
|
||||
if (Array.isArray(ordersForStock)) {
|
||||
for (const order of ordersForStock) {
|
||||
if (order instanceof Order && order.stock instanceof Stock) {
|
||||
order.stockSymbol = order.stock.symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(`Converted Stock Market order book to v0.47.0 format`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,7 +202,7 @@ export function stockMarketCycle() {
|
||||
if (stock.b) { thresh = 0.4; }
|
||||
if (Math.random() < thresh) {
|
||||
stock.b = !stock.b;
|
||||
if (stock.otlkMag < 10) { stock.otlkMag += 0.4; }
|
||||
if (stock.otlkMag < 10) { stock.otlkMag += 0.2; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -220,15 +247,16 @@ export function processStockPrices(numCycles=1) {
|
||||
const processOrderRefs = {
|
||||
rerenderFn: displayStockMarketContent,
|
||||
stockMarket: StockMarket,
|
||||
symbolToStockMap: SymbolToStockMap,
|
||||
}
|
||||
if (c < chc) {
|
||||
stock.price *= (1 + av);
|
||||
stock.changePrice(stock.price * (1 + av));
|
||||
processOrders(stock, OrderTypes.LimitBuy, PositionTypes.Short, processOrderRefs);
|
||||
processOrders(stock, OrderTypes.LimitSell, PositionTypes.Long, processOrderRefs);
|
||||
processOrders(stock, OrderTypes.StopBuy, PositionTypes.Long, processOrderRefs);
|
||||
processOrders(stock, OrderTypes.StopSell, PositionTypes.Short, processOrderRefs);
|
||||
} else {
|
||||
stock.price /= (1 + av);
|
||||
stock.changePrice(stock.price / (1 + av));
|
||||
processOrders(stock, OrderTypes.LimitBuy, PositionTypes.Long, processOrderRefs);
|
||||
processOrders(stock, OrderTypes.LimitSell, PositionTypes.Short, processOrderRefs);
|
||||
processOrders(stock, OrderTypes.StopBuy, PositionTypes.Short, processOrderRefs);
|
||||
|
@ -3,7 +3,7 @@ import { PositionTypes } from "./data/PositionTypes";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
|
||||
// Amount by which a stock's forecast changes during each price movement
|
||||
export const forecastChangePerPriceMovement = 0.4;
|
||||
export const forecastChangePerPriceMovement = 0.1;
|
||||
|
||||
/**
|
||||
* Given a stock, calculates the amount by which the stock price is multiplied
|
||||
@ -118,7 +118,7 @@ export function processBuyTransactionPriceMovement(stock: Stock, shares: number,
|
||||
if (stock.shareTxUntilMovement <= 0) {
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
stock.price = currPrice;
|
||||
stock.changePrice(currPrice);
|
||||
stock.otlkMag -= (forecastChangePerPriceMovement);
|
||||
}
|
||||
|
||||
@ -140,11 +140,15 @@ export function processBuyTransactionPriceMovement(stock: Stock, shares: number,
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
}
|
||||
stock.price = currPrice;
|
||||
stock.changePrice(currPrice);
|
||||
|
||||
// Forecast always decreases in magnitude
|
||||
const forecastChange = Math.min(5, forecastChangePerPriceMovement * (numIterations - 1));
|
||||
stock.otlkMag -= forecastChange;
|
||||
if (stock.otlkMag < 0) {
|
||||
stock.b = !stock.b;
|
||||
stock.otlkMag = Math.abs(stock.otlkMag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,7 +246,7 @@ export function processSellTransactionPriceMovement(stock: Stock, shares: number
|
||||
if (stock.shareTxUntilMovement <= 0) {
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
stock.price = currPrice;
|
||||
stock.changePrice(currPrice);
|
||||
stock.otlkMag -= (forecastChangePerPriceMovement);
|
||||
}
|
||||
|
||||
@ -263,11 +267,15 @@ export function processSellTransactionPriceMovement(stock: Stock, shares: number
|
||||
stock.shareTxUntilMovement = stock.shareTxForMovement;
|
||||
processPriceMovement();
|
||||
}
|
||||
stock.price = currPrice;
|
||||
stock.changePrice(currPrice);
|
||||
|
||||
// Forecast always decreases in magnitude
|
||||
const forecastChange = Math.min(5, forecastChangePerPriceMovement * (numIterations - 1));
|
||||
stock.otlkMag -= forecastChange;
|
||||
if (stock.otlkMag < 0) {
|
||||
stock.b = !stock.b;
|
||||
stock.otlkMag = Math.abs(stock.otlkMag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,8 +33,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 1,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.AevumECorp],
|
||||
},
|
||||
@ -59,8 +59,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 1,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.Sector12MegaCorp],
|
||||
},
|
||||
@ -85,8 +85,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 1,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.Sector12BladeIndustries],
|
||||
},
|
||||
@ -111,8 +111,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 1,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.AevumClarkeIncorporated],
|
||||
},
|
||||
@ -137,8 +137,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 1,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.VolhavenOmniTekIncorporated],
|
||||
},
|
||||
@ -163,8 +163,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 1,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.Sector12FourSigma],
|
||||
},
|
||||
@ -189,8 +189,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 1,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.ChongqingKuaiGongInternational],
|
||||
},
|
||||
@ -215,8 +215,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 1,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.AevumFulcrumTechnologies],
|
||||
},
|
||||
@ -241,8 +241,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 2,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 36e3,
|
||||
min: 12e3,
|
||||
max: 54e3,
|
||||
min: 18e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.IshimaStormTechnologies],
|
||||
},
|
||||
@ -267,8 +267,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 2,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 36e3,
|
||||
min: 12e3,
|
||||
max: 54e3,
|
||||
min: 18e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.NewTokyoDefComm],
|
||||
},
|
||||
@ -293,8 +293,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 2,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 36e3,
|
||||
min: 12e3,
|
||||
max: 54e3,
|
||||
min: 18e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.VolhavenHeliosLabs],
|
||||
},
|
||||
@ -319,8 +319,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 2,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 36e3,
|
||||
min: 12e3,
|
||||
max: 54e3,
|
||||
min: 18e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.NewTokyoVitaLife],
|
||||
},
|
||||
@ -345,8 +345,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 3,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 36e3,
|
||||
min: 12e3,
|
||||
max: 54e3,
|
||||
min: 18e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.Sector12IcarusMicrosystems],
|
||||
},
|
||||
@ -371,8 +371,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 2,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 36e3,
|
||||
min: 12e3,
|
||||
max: 54e3,
|
||||
min: 18e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.Sector12UniversalEnergy],
|
||||
},
|
||||
@ -397,8 +397,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 3,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 42e3,
|
||||
min: 14e3,
|
||||
max: 63e3,
|
||||
min: 21e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.AevumAeroCorp],
|
||||
},
|
||||
@ -423,8 +423,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 4,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 42e3,
|
||||
min: 14e3,
|
||||
max: 63e3,
|
||||
min: 21e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.VolhavenOmniaCybersystems],
|
||||
},
|
||||
@ -449,8 +449,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 4,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 42e3,
|
||||
min: 14e3,
|
||||
max: 63e3,
|
||||
min: 21e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.ChongqingSolarisSpaceSystems],
|
||||
},
|
||||
@ -475,8 +475,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 4,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 42e3,
|
||||
min: 14e3,
|
||||
max: 63e3,
|
||||
min: 21e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.NewTokyoGlobalPharmaceuticals],
|
||||
},
|
||||
@ -501,8 +501,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 4,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 42e3,
|
||||
min: 14e3,
|
||||
max: 63e3,
|
||||
min: 21e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.IshimaNovaMedical],
|
||||
},
|
||||
@ -527,8 +527,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 5,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 18e3,
|
||||
min: 4e3,
|
||||
max: 27e3,
|
||||
min: 6e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.AevumWatchdogSecurity],
|
||||
},
|
||||
@ -553,8 +553,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 5,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 36e3,
|
||||
min: 12e3,
|
||||
max: 54e3,
|
||||
min: 18e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.VolhavenLexoCorp],
|
||||
},
|
||||
@ -579,8 +579,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 3,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 42e3,
|
||||
min: 20e3,
|
||||
max: 63e3,
|
||||
min: 30e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.AevumRhoConstruction],
|
||||
},
|
||||
@ -605,8 +605,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 5,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.Sector12AlphaEnterprises],
|
||||
},
|
||||
@ -631,8 +631,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 5,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.VolhavenSysCoreSecurities],
|
||||
},
|
||||
@ -657,8 +657,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 4,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 42e3,
|
||||
min: 20e3,
|
||||
max: 63e3,
|
||||
min: 30e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.VolhavenCompuTek],
|
||||
},
|
||||
@ -683,8 +683,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 5,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 18e3,
|
||||
min: 6e3,
|
||||
max: 27e3,
|
||||
min: 9e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.AevumNetLinkTechnologies],
|
||||
},
|
||||
@ -709,8 +709,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 4,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 30e3,
|
||||
min: 10e3,
|
||||
max: 45e3,
|
||||
min: 15e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.IshimaOmegaSoftware],
|
||||
},
|
||||
@ -735,8 +735,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 6,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 60e3,
|
||||
min: 20e3,
|
||||
max: 90e3,
|
||||
min: 30e3,
|
||||
},
|
||||
symbol: StockSymbols[LocationName.Sector12FoodNStuff],
|
||||
},
|
||||
@ -761,8 +761,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 6,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 28e3,
|
||||
min: 8e3,
|
||||
max: 42e3,
|
||||
min: 12e3,
|
||||
},
|
||||
symbol: StockSymbols["Sigma Cosmetics"],
|
||||
},
|
||||
@ -787,8 +787,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 6,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 21e3,
|
||||
min: 6e3,
|
||||
max: 32e3,
|
||||
min: 9e3,
|
||||
},
|
||||
symbol: StockSymbols["Joes Guns"],
|
||||
},
|
||||
@ -813,8 +813,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 5,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 24e3,
|
||||
min: 8e3,
|
||||
max: 36e3,
|
||||
min: 12e3,
|
||||
},
|
||||
symbol: StockSymbols["Catalyst Ventures"],
|
||||
},
|
||||
@ -839,8 +839,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 3,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 72e3,
|
||||
min: 30e3,
|
||||
max: 108e3,
|
||||
min: 45e3,
|
||||
},
|
||||
symbol: StockSymbols["Microdyne Technologies"],
|
||||
},
|
||||
@ -865,8 +865,8 @@ export const InitStockMetadata: IConstructorParams[] = [
|
||||
min: 2,
|
||||
},
|
||||
shareTxForMovement: {
|
||||
max: 72e3,
|
||||
min: 30e3,
|
||||
max: 108e3,
|
||||
min: 45e3,
|
||||
},
|
||||
symbol: StockSymbols["Titan Laboratories"],
|
||||
},
|
||||
|
@ -24,7 +24,9 @@ export function StockTickerHeaderText(props: IProps): React.ReactElement {
|
||||
let hdrText = `${stock.name}${" ".repeat(1 + TickerHeaderFormatData.longestName - stock.name.length + (TickerHeaderFormatData.longestSymbol - stock.symbol.length))}${stock.symbol} -${" ".repeat(10 - stockPriceFormat.length)}${stockPriceFormat}`;
|
||||
if (props.p.has4SData) {
|
||||
hdrText += ` - Volatility: ${numeralWrapper.format(stock.mv, '0,0.00')}% - Price Forecast: `;
|
||||
hdrText += (stock.b ? "+" : "-").repeat(Math.floor(stock.otlkMag / 10) + 1);
|
||||
let plusOrMinus = stock.b; // True for "+", false for "-"
|
||||
if (stock.otlkMag < 0) { plusOrMinus = !plusOrMinus }
|
||||
hdrText += (plusOrMinus ? "+" : "-").repeat(Math.floor(Math.abs(stock.otlkMag) / 10) + 1);
|
||||
}
|
||||
|
||||
let styleMarkup = {
|
||||
|
17
test/Netscript/StaticRamCalculationTests.js
Normal file
17
test/Netscript/StaticRamCalculationTests.js
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* TODO This should also test the calcualteRamUsage() function from
|
||||
* /Script/RamCalculations but there's some issues with getting tests to run
|
||||
* when any npm package is included in the build (/Script/RamCalculations includes
|
||||
* walk from acorn).
|
||||
*/
|
||||
import { getRamCost } from "../../src/Netscript/RamCostGenerator";
|
||||
//import { calculateRamUsage } from "../../src/Script/RamCalculations"
|
||||
|
||||
const assert = chai.assert;
|
||||
const expect = chai.expect;
|
||||
|
||||
console.log("Beginning Netscript Static RAM Calculation/Generation Tests");
|
||||
|
||||
describe("Netscript Static RAM Calculation/Generation Tests", function() {
|
||||
|
||||
});
|
5
test/README.md
Normal file
5
test/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Unit Tests
|
||||
This directory contains unit tests for Bitburner.
|
||||
|
||||
Unit tests use Mocha/Chai and are run through the browser. The Mocha/Chai
|
||||
packages are sourced directly in HTML.
|
@ -1,7 +1,8 @@
|
||||
import { CONSTANTS } from "../src/Constants";
|
||||
import { Order } from "../src/StockMarket/Order";
|
||||
//import { processOrders } from "../src/StockMarket/OrderProcessing";
|
||||
// import { Stock } from "../src/StockMarket/Stock";
|
||||
import { Stock } from "../src/StockMarket/Stock";
|
||||
/*
|
||||
import {
|
||||
deleteStockMarket,
|
||||
initStockMarket,
|
||||
@ -10,7 +11,7 @@ import {
|
||||
StockMarket,
|
||||
SymbolToStockMap,
|
||||
} from "../src/StockMarket/StockMarket";
|
||||
/*
|
||||
*/
|
||||
import {
|
||||
calculateIncreasingPriceMovement,
|
||||
calculateDecreasingPriceMovement,
|
||||
@ -20,9 +21,8 @@ import {
|
||||
processBuyTransactionPriceMovement,
|
||||
processSellTransactionPriceMovement,
|
||||
} from "../src/StockMarket/StockMarketHelpers";
|
||||
*/
|
||||
// import { OrderTypes } from "../src/StockMarket/data/OrderTypes"
|
||||
// import { PositionTypes } from "../src/StockMarket/data/PositionTypes";
|
||||
import { OrderTypes } from "../src/StockMarket/data/OrderTypes"
|
||||
import { PositionTypes } from "../src/StockMarket/data/PositionTypes";
|
||||
|
||||
const assert = chai.assert;
|
||||
const expect = chai.expect;
|
||||
@ -158,6 +158,8 @@ describe("Stock Market Tests", function() {
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
// TODO These tests fail due to circular dependency errors
|
||||
describe("StockMarket object", function() {
|
||||
describe("Initialization", function() {
|
||||
// Keeps track of initialized stocks. Contains their symbols
|
||||
@ -218,6 +220,7 @@ describe("Stock Market Tests", function() {
|
||||
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
describe("Transaction Cost Calculator Functions", function() {
|
||||
describe("getBuyTransactionCost()", function() {
|
||||
@ -644,16 +647,16 @@ describe("Stock Market Tests", function() {
|
||||
return new Order({}, 1, 1, OrderTypes.LimitBuy, PositionTypes.Long);
|
||||
}
|
||||
function invalid2() {
|
||||
return new Order(new Stock(), "z", 0, OrderTypes.LimitBuy, PositionTypes.Short);
|
||||
return new Order("FOO", "z", 0, OrderTypes.LimitBuy, PositionTypes.Short);
|
||||
}
|
||||
function invalid3() {
|
||||
return new Order(new Stock(), 1, {}, OrderTypes.LimitBuy, PositionTypes.Short);
|
||||
return new Order("FOO", 1, {}, OrderTypes.LimitBuy, PositionTypes.Short);
|
||||
}
|
||||
function invalid4() {
|
||||
return new Order(new Stock(), 1, NaN, OrderTypes.LimitBuy, PositionTypes.Short);
|
||||
return new Order("FOO", 1, NaN, OrderTypes.LimitBuy, PositionTypes.Short);
|
||||
}
|
||||
function invalid5() {
|
||||
return new Order(new Stock(), NaN, 0, OrderTypes.LimitBuy, PositionTypes.Short);
|
||||
return new Order("FOO", NaN, 0, OrderTypes.LimitBuy, PositionTypes.Short);
|
||||
}
|
||||
|
||||
expect(invalid1).to.throw();
|
@ -8,15 +8,16 @@
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
|
||||
<script src="https://unpkg.com/chai/chai.js"></script>
|
||||
<script src="https://unpkg.com/mocha/mocha.js"></script>
|
||||
<script defer src="https://unpkg.com/chai/chai.js"></script>
|
||||
<script defer src="https://unpkg.com/mocha/mocha.js"></script>
|
||||
|
||||
<script class="mocha-init">
|
||||
<script type="module" class="mocha-init">
|
||||
mocha.setup('bdd');
|
||||
mocha.checkLeaks();
|
||||
</script>
|
||||
<script type="module" src="tests.bundle.js"></script>
|
||||
<script class="mocha-exec" type="module">
|
||||
console.log("Running Tests");
|
||||
mocha.run();
|
||||
</script>
|
||||
</body>
|
2
test/index.js
Normal file
2
test/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
export * from "./Netscript/StaticRamCalculationTests";
|
||||
export * from "./StockMarketTests";
|
2035
test/tests.bundle.js
Normal file
2035
test/tests.bundle.js
Normal file
File diff suppressed because it is too large
Load Diff
1
test/tests.bundle.js.map
Normal file
1
test/tests.bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
4889
test/tests.css
Normal file
4889
test/tests.css
Normal file
File diff suppressed because it is too large
Load Diff
1
test/tests.css.map
Normal file
1
test/tests.css.map
Normal file
File diff suppressed because one or more lines are too long
@ -1,52 +0,0 @@
|
||||
import {executeJSScript} from "../src/NetscriptJSEvaluator.js";
|
||||
import {WorkerScript} from "../src/NetscriptWorker.js";
|
||||
|
||||
const chai = require("chai");
|
||||
const chaiAsPromised = require("chai-as-promised");
|
||||
chai.should();
|
||||
chai.use(chaiAsPromised);
|
||||
|
||||
console.info('asdf');
|
||||
|
||||
describe('NSJS ScriptStore', function() {
|
||||
it('should run an imported function', async function() {
|
||||
const s = { filename: "", code: "export function main() { return 2; }", args:[]};
|
||||
const worker = new WorkerScript(s);
|
||||
chai.expect(await executeJSScript([], s)).to.equal(2);
|
||||
});
|
||||
|
||||
/*
|
||||
it('should handle recursive imports', async function() {
|
||||
const s1 = { filename: "s1.js", code: "export function iAmRecursiveImport(x) { return x + 2; }" };
|
||||
const s2 = { filename: "", code: `
|
||||
import {iAmRecursiveImport} from \"s1.js\";
|
||||
export function main() { return iAmRecursiveImport(3);
|
||||
}`};
|
||||
chai.expect(await executeJSScript([s1, s2], s2)).to.equal(5);
|
||||
});
|
||||
|
||||
it (`should correctly reference the passed global env`, async function() {
|
||||
var [x, y] = [0, 0];
|
||||
var env = {
|
||||
updateX: function(value) { x = value; },
|
||||
updateY: function(value) { y = value; },
|
||||
};
|
||||
const s1 = {filename: "s1.js", code: "export function importedFn(x) { updateX(x); }"};
|
||||
const s2 = {filename: "s2.js", code: `
|
||||
import {importedFn} from "s1.js";
|
||||
export function main() { updateY(7); importedFn(3); }
|
||||
`}
|
||||
await executeJSScript(s2, [s1, s2], env);
|
||||
chai.expect(y).to.equal(7);
|
||||
chai.expect(x).to.equal(3);
|
||||
});
|
||||
|
||||
it (`should throw on circular dep`, async function() {
|
||||
const s1 = {filename: "s1.js", code: "import \"s2.js\""};
|
||||
const s2 = {filename: "s2.js", code: `
|
||||
import * as s1 from "s1.js";
|
||||
export function main() {}
|
||||
`}
|
||||
executeJSScript(s2, [s1, s2]).should.eventually.throw();
|
||||
});*/
|
||||
});
|
@ -1 +0,0 @@
|
||||
export * from "./StockMarketTests";
|
@ -10,7 +10,18 @@ module.exports = (env, argv) => {
|
||||
const entries = {};
|
||||
entries[`${outputDirectory}/engine`] = "./src/engine.jsx";
|
||||
if (!isDevServer) {
|
||||
entries["tests/tests"] = "./tests/index.js";
|
||||
entries["test/tests"] = "./test/index.js";
|
||||
}
|
||||
|
||||
const statsConfig = {
|
||||
builtAt: true,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkGroups: false,
|
||||
chunkModules: false,
|
||||
chunkOrigins: false,
|
||||
colors: true,
|
||||
entrypoints: true,
|
||||
}
|
||||
|
||||
return {
|
||||
@ -63,7 +74,7 @@ module.exports = (env, argv) => {
|
||||
useShortDoctype: false
|
||||
},
|
||||
excludeChunks: [
|
||||
"tests/tests"
|
||||
"test/tests"
|
||||
]
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
@ -128,6 +139,7 @@ module.exports = (env, argv) => {
|
||||
devServer: {
|
||||
port: 8000,
|
||||
publicPath: `/`,
|
||||
stats: statsConfig,
|
||||
},
|
||||
resolve: {
|
||||
extensions: [
|
||||
@ -136,6 +148,7 @@ module.exports = (env, argv) => {
|
||||
".js",
|
||||
".jsx",
|
||||
]
|
||||
}
|
||||
},
|
||||
stats: statsConfig,
|
||||
};
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user