Fixed merge conflcits with dev

This commit is contained in:
danielyxie 2019-05-17 13:50:27 -07:00
commit 287a97aea6
21 changed files with 343 additions and 246843 deletions

74647
dist/engine.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -1,541 +1,2 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // install a JSONP callback for chunk loading
/******/ function webpackJsonpCallback(data) {
/******/ var chunkIds = data[0];
/******/ var moreModules = data[1];
/******/ var executeModules = data[2];
/******/
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0, resolves = [];
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(installedChunks[chunkId]) {
/******/ resolves.push(installedChunks[chunkId][0]);
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/ for(moduleId in moreModules) {
/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
/******/ modules[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(parentJsonpFunction) parentJsonpFunction(data);
/******/
/******/ while(resolves.length) {
/******/ resolves.shift()();
/******/ }
/******/
/******/ // add entry modules from loaded chunk to deferred list
/******/ deferredModules.push.apply(deferredModules, executeModules || []);
/******/
/******/ // run deferred modules when all chunks ready
/******/ return checkDeferredModules();
/******/ };
/******/ function checkDeferredModules() {
/******/ var result;
/******/ for(var i = 0; i < deferredModules.length; i++) {
/******/ var deferredModule = deferredModules[i];
/******/ var fulfilled = true;
/******/ for(var j = 1; j < deferredModule.length; j++) {
/******/ var depId = deferredModule[j];
/******/ if(installedChunks[depId] !== 0) fulfilled = false;
/******/ }
/******/ if(fulfilled) {
/******/ deferredModules.splice(i--, 1);
/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]);
/******/ }
/******/ }
/******/ return result;
/******/ }
/******/
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // Promise = chunk loading, 0 = chunk loaded
/******/ var installedChunks = {
/******/ 1: 0
/******/ };
/******/
/******/ var deferredModules = [];
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
/******/ jsonpArray.push = webpackJsonpCallback;
/******/ jsonpArray = jsonpArray.slice();
/******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
/******/ var parentJsonpFunction = oldJsonpFunction;
/******/
/******/
/******/ // add entry module to deferred list
/******/ deferredModules.push([352,0]);
/******/ // run deferred modules when ready
/******/ return checkDeferredModules();
/******/ })
/************************************************************************/
/******/ ({
/***/ 299:
/*!**************************!*\
!*** ./css/dev-menu.css ***!
\**************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 301:
/*!**************************!*\
!*** ./css/grid.min.css ***!
\**************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 303:
/*!************************!*\
!*** ./css/treant.css ***!
\************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 305:
/*!*****************************!*\
!*** ./css/resleeving.scss ***!
\*****************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 307:
/*!**************************!*\
!*** ./css/sleeves.scss ***!
\**************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 309:
/*!***********************!*\
!*** ./css/gang.scss ***!
\***********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 311:
/*!******************************!*\
!*** ./css/bladeburner.scss ***!
\******************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 313:
/*!************************************!*\
!*** ./css/companymanagement.scss ***!
\************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 315:
/*!***************************!*\
!*** ./css/missions.scss ***!
\***************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 317:
/*!*************************!*\
!*** ./css/loader.scss ***!
\*************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 319:
/*!**************************************!*\
!*** ./css/interactivetutorial.scss ***!
\**************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 321:
/*!******************************!*\
!*** ./css/gameoptions.scss ***!
\******************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 323:
/*!*****************************!*\
!*** ./css/popupboxes.scss ***!
\*****************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 325:
/*!*********************************!*\
!*** ./css/workinprogress.scss ***!
\*********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 327:
/*!******************************!*\
!*** ./css/stockmarket.scss ***!
\******************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 329:
/*!**************************!*\
!*** ./css/redpill.scss ***!
\**************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 331:
/*!****************************!*\
!*** ./css/menupages.scss ***!
\****************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 333:
/*!*******************************!*\
!*** ./css/hacknetnodes.scss ***!
\*******************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 335:
/*!***************************************!*\
!*** ./css/codemirror-overrides.scss ***!
\***************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 337:
/*!*******************************!*\
!*** ./css/scripteditor.scss ***!
\*******************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 339:
/*!***************************!*\
!*** ./css/terminal.scss ***!
\***************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 341:
/*!************************************!*\
!*** ./css/characteroverview.scss ***!
\************************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 343:
/*!***************************!*\
!*** ./css/mainmenu.scss ***!
\***************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 345:
/*!**************************!*\
!*** ./css/buttons.scss ***!
\**************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 347:
/*!***************************!*\
!*** ./css/tooltips.scss ***!
\***************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 349:
/*!*************************!*\
!*** ./css/styles.scss ***!
\*************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// extracted by mini-css-extract-plugin
/***/ }),
/***/ 352:
/*!****************************!*\
!*** ./src/engineStyle.js ***!
\****************************/
/*! no exports provided */
/*! all exports used */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var normalize_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! normalize.css */ 351);
/* harmony import */ var normalize_css__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(normalize_css__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _css_styles_scss__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../css/styles.scss */ 349);
/* harmony import */ var _css_styles_scss__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_css_styles_scss__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _css_tooltips_scss__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../css/tooltips.scss */ 347);
/* harmony import */ var _css_tooltips_scss__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_css_tooltips_scss__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _css_buttons_scss__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../css/buttons.scss */ 345);
/* harmony import */ var _css_buttons_scss__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_css_buttons_scss__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _css_mainmenu_scss__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../css/mainmenu.scss */ 343);
/* harmony import */ var _css_mainmenu_scss__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_css_mainmenu_scss__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var _css_characteroverview_scss__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../css/characteroverview.scss */ 341);
/* harmony import */ var _css_characteroverview_scss__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_css_characteroverview_scss__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var _css_terminal_scss__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../css/terminal.scss */ 339);
/* harmony import */ var _css_terminal_scss__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_css_terminal_scss__WEBPACK_IMPORTED_MODULE_6__);
/* harmony import */ var _css_scripteditor_scss__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../css/scripteditor.scss */ 337);
/* harmony import */ var _css_scripteditor_scss__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_css_scripteditor_scss__WEBPACK_IMPORTED_MODULE_7__);
/* harmony import */ var _css_codemirror_overrides_scss__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../css/codemirror-overrides.scss */ 335);
/* harmony import */ var _css_codemirror_overrides_scss__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(_css_codemirror_overrides_scss__WEBPACK_IMPORTED_MODULE_8__);
/* harmony import */ var _css_hacknetnodes_scss__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../css/hacknetnodes.scss */ 333);
/* harmony import */ var _css_hacknetnodes_scss__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(_css_hacknetnodes_scss__WEBPACK_IMPORTED_MODULE_9__);
/* harmony import */ var _css_menupages_scss__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../css/menupages.scss */ 331);
/* harmony import */ var _css_menupages_scss__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(_css_menupages_scss__WEBPACK_IMPORTED_MODULE_10__);
/* harmony import */ var _css_redpill_scss__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../css/redpill.scss */ 329);
/* harmony import */ var _css_redpill_scss__WEBPACK_IMPORTED_MODULE_11___default = /*#__PURE__*/__webpack_require__.n(_css_redpill_scss__WEBPACK_IMPORTED_MODULE_11__);
/* harmony import */ var _css_stockmarket_scss__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../css/stockmarket.scss */ 327);
/* harmony import */ var _css_stockmarket_scss__WEBPACK_IMPORTED_MODULE_12___default = /*#__PURE__*/__webpack_require__.n(_css_stockmarket_scss__WEBPACK_IMPORTED_MODULE_12__);
/* harmony import */ var _css_workinprogress_scss__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../css/workinprogress.scss */ 325);
/* harmony import */ var _css_workinprogress_scss__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(_css_workinprogress_scss__WEBPACK_IMPORTED_MODULE_13__);
/* harmony import */ var _css_popupboxes_scss__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../css/popupboxes.scss */ 323);
/* harmony import */ var _css_popupboxes_scss__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(_css_popupboxes_scss__WEBPACK_IMPORTED_MODULE_14__);
/* harmony import */ var _css_gameoptions_scss__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../css/gameoptions.scss */ 321);
/* harmony import */ var _css_gameoptions_scss__WEBPACK_IMPORTED_MODULE_15___default = /*#__PURE__*/__webpack_require__.n(_css_gameoptions_scss__WEBPACK_IMPORTED_MODULE_15__);
/* harmony import */ var _css_interactivetutorial_scss__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../css/interactivetutorial.scss */ 319);
/* harmony import */ var _css_interactivetutorial_scss__WEBPACK_IMPORTED_MODULE_16___default = /*#__PURE__*/__webpack_require__.n(_css_interactivetutorial_scss__WEBPACK_IMPORTED_MODULE_16__);
/* harmony import */ var _css_loader_scss__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../css/loader.scss */ 317);
/* harmony import */ var _css_loader_scss__WEBPACK_IMPORTED_MODULE_17___default = /*#__PURE__*/__webpack_require__.n(_css_loader_scss__WEBPACK_IMPORTED_MODULE_17__);
/* harmony import */ var _css_missions_scss__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../css/missions.scss */ 315);
/* harmony import */ var _css_missions_scss__WEBPACK_IMPORTED_MODULE_18___default = /*#__PURE__*/__webpack_require__.n(_css_missions_scss__WEBPACK_IMPORTED_MODULE_18__);
/* harmony import */ var _css_companymanagement_scss__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../css/companymanagement.scss */ 313);
/* harmony import */ var _css_companymanagement_scss__WEBPACK_IMPORTED_MODULE_19___default = /*#__PURE__*/__webpack_require__.n(_css_companymanagement_scss__WEBPACK_IMPORTED_MODULE_19__);
/* harmony import */ var _css_bladeburner_scss__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ../css/bladeburner.scss */ 311);
/* harmony import */ var _css_bladeburner_scss__WEBPACK_IMPORTED_MODULE_20___default = /*#__PURE__*/__webpack_require__.n(_css_bladeburner_scss__WEBPACK_IMPORTED_MODULE_20__);
/* harmony import */ var _css_gang_scss__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ../css/gang.scss */ 309);
/* harmony import */ var _css_gang_scss__WEBPACK_IMPORTED_MODULE_21___default = /*#__PURE__*/__webpack_require__.n(_css_gang_scss__WEBPACK_IMPORTED_MODULE_21__);
/* harmony import */ var _css_sleeves_scss__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ../css/sleeves.scss */ 307);
/* harmony import */ var _css_sleeves_scss__WEBPACK_IMPORTED_MODULE_22___default = /*#__PURE__*/__webpack_require__.n(_css_sleeves_scss__WEBPACK_IMPORTED_MODULE_22__);
/* harmony import */ var _css_resleeving_scss__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ../css/resleeving.scss */ 305);
/* harmony import */ var _css_resleeving_scss__WEBPACK_IMPORTED_MODULE_23___default = /*#__PURE__*/__webpack_require__.n(_css_resleeving_scss__WEBPACK_IMPORTED_MODULE_23__);
/* harmony import */ var _css_treant_css__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ../css/treant.css */ 303);
/* harmony import */ var _css_treant_css__WEBPACK_IMPORTED_MODULE_24___default = /*#__PURE__*/__webpack_require__.n(_css_treant_css__WEBPACK_IMPORTED_MODULE_24__);
/* harmony import */ var _css_grid_min_css__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ../css/grid.min.css */ 301);
/* harmony import */ var _css_grid_min_css__WEBPACK_IMPORTED_MODULE_25___default = /*#__PURE__*/__webpack_require__.n(_css_grid_min_css__WEBPACK_IMPORTED_MODULE_25__);
/* harmony import */ var _css_dev_menu_css__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ../css/dev-menu.css */ 299);
/* harmony import */ var _css_dev_menu_css__WEBPACK_IMPORTED_MODULE_26___default = /*#__PURE__*/__webpack_require__.n(_css_dev_menu_css__WEBPACK_IMPORTED_MODULE_26__);
// These should really be imported with the module that is presenting that UI, but because they very much depend on the
// cascade order, we'll pull them all in here.
/***/ })
/******/ });
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],r[i]&&s.push(r[i][0]),r[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return u.push.apply(u,l||[]),o()}function o(){for(var n,t=0;t<u.length;t++){for(var o=u[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==r[c]&&(e=!1)}e&&(u.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},r={1:0},u=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;u.push([353,0]),o()}({300:function(n,t,o){},302:function(n,t,o){},304:function(n,t,o){},306:function(n,t,o){},308:function(n,t,o){},310:function(n,t,o){},312:function(n,t,o){},314:function(n,t,o){},316:function(n,t,o){},318:function(n,t,o){},320:function(n,t,o){},322:function(n,t,o){},324:function(n,t,o){},326:function(n,t,o){},328:function(n,t,o){},330:function(n,t,o){},332:function(n,t,o){},334:function(n,t,o){},336:function(n,t,o){},338:function(n,t,o){},340:function(n,t,o){},342:function(n,t,o){},344:function(n,t,o){},346:function(n,t,o){},348:function(n,t,o){},350:function(n,t,o){},353:function(n,t,o){"use strict";o.r(t);o(352),o(350),o(348),o(346),o(344),o(342),o(340),o(338),o(336),o(334),o(332),o(330),o(328),o(326),o(324),o(322),o(320),o(318),o(316),o(314),o(312),o(310),o(308),o(306),o(304),o(302),o(300)}});
//# sourceMappingURL=engineStyle.bundle.js.map

171535
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -86,8 +86,11 @@ Sleeve memory dictates what a sleeve's synchronization will be when its reset by
switching BitNodes. For example, if a sleeve has a memory of 10, then when you
switch BitNodes its synchronization will initially be set to 10, rather than 1.
Memory can only be increased by purchasing upgrades from The Covenant.
It is a persistent stat, meaning it never gets reset back to 1.
Memory can only be increased by purchasing upgrades from The Covenant. Just like
the ability to purchase additional sleeves, this is only available in BitNodes-10
and above, and is only available after defeating BitNode-10 at least once.
Memory is a persistent stat, meaning it never gets reset back to 1.
The maximum possible value for a sleeve's memory is 100.
Re-sleeving

@ -3,6 +3,50 @@
Changelog
=========
v0.47.0 - 5/17/2019
-------------------
* Stock Market changes:
* Implemented spread. Stock's now have bid and ask prices at which transactions occur
* Large transactions will now influence a stock's price and forecast
* This "influencing" can take effect in the middle of a transaction
* See documentation for more details on these changes
* Added getStockAskPrice(), getStockBidPrice() Netscript functions to the TIX API
* Added getStockPurchaseCost(), getStockSaleGain() Netscript functions to the TIX API
* Re-sleeves can no longer have the NeuroFlux Governor augmentation
* This is just a temporary patch until the mechanic gets re-worked
* hack(), grow(), and weaken() functions now take optional arguments for number of threads to use (by MasonD)
* codingcontract.attempt() now takes an optional argument that allows you to configure the function to return a contract's reward
* Adjusted RAM costs of Netscript Singularity functions (mostly increased)
* Adjusted RAM cost of codingcontract.getNumTriesRemaining() Netscript function
* Netscript Singularity functions no longer cost extra RAM outside of BitNode-4
* Corporation employees no longer have an "age" stat
* Gang Wanted level gain rate capped at 100 (per employee)
* Script startup/kill is now processed every 3 seconds, instead of 6 seconds
* getHackTime(), getGrowTime(), and getWeakenTime() now return Infinity if called on a Hacknet Server
* Money/Income tracker now displays money lost from hospitalizations
* Exported saves now have a unique filename based on current BitNode and timestamp
* Maximum number of Hacknet Servers decreased from 25 to 20
* Bug Fix: Corporation employees stats should no longer become negative
* Bug Fix: Fixed sleeve.getInformation() throwing error in certain scenarios
* Bug Fix: Coding contracts should no longer generate on the w0r1d_d43m0n server
* Bug Fix: Duplicate Sleeves now properly have access to all Augmentations if you have a gang
* Bug Fix: getAugmentationsFromFaction() & purchaseAugmentation() functions should now work properly if you have a gang
* Bug Fix: Fixed issue that caused messages (.msg) to be sent when refreshing/reloading the game
* Bug Fix: Purchasing hash upgrades for Bladeburner/Corporation when you don't actually have access to those mechanics no longer gives hashes
* Bug Fix: run(), exec(), and spawn() Netscript functions now throw if called with 0 threads
* Bug Fix: Faction UI should now automatically update reputation
* Bug Fix: Fixed purchase4SMarketData()
* Bug Fix: Netscript1.0 now works properly for multiple 'namespace' imports (import * as namespace from "script")
* Bug Fix: Terminal 'wget' command now correctly evaluates directory paths
* Bug Fix: wget(), write(), and scp() Netscript functions now fail if an invalid filepath is passed in
* Bug Fix: Having Corporation warehouses at full capacity should no longer freeze game in certain conditions
* Bug Fix: Prevented an exploit that allows you to buy multiple copies of an Augmentation by holding the 'Enter' button
* Bug Fix: gang.getOtherGangInformation() now properly returns a deep copy
* Bug Fix: Fixed getScriptIncome() returning an undefined value
* Bug Fix: Fixed an issue with Hacknet Server hash rate not always updating
v0.46.3 - 4/20/2019
-------------------
* Added a new Augmentation: The Shadow's Simulacrum

@ -64,9 +64,9 @@ documentation_title = '{0} Documentation'.format(project)
# built documents.
#
# The short X.Y version.
version = '0.46'
version = '0.47'
# The full version, including alpha/beta/rc tags.
release = '0.46.3'
release = '0.47.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

@ -21,4 +21,13 @@ hackAnalyzeThreads() Netscript Function
If this function returns 50, this means that if your next `hack()` call
is run on a script with 50 threads, it will steal $1m from the `foodnstuff` server.
**Warning**: The value returned by this function isn't necessarily a whole number.
.. warning:: The value returned by this function isn't necessarily a whole number.
.. warning:: It is possible for this function to return :code:`Infinity` or :code:`NaN` in
certain uncommon scenarios. This is because in JavaScript:
* :code:`0 / 0 = NaN`
* :code:`N / 0 = Infinity` for 0 < N < Infinity.
For example, if a server has no money available and you want to hack some positive
amount from it, then the function would return :code:`Infinity` because
this would be impossible.

@ -8,8 +8,7 @@ later in the game
.. warning:: This page contains spoilers for the game
The Gang API is unlocked in BitNode-2. Currently, BitNode-2 is the only location
where the Gang mechanic is accessible. This may change in the future
The Gang mechanic and the Gang API are unlocked in BitNode-2.
**Gang API functions must be accessed through the 'gang' namespace**

@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bitburner - development</title>
<title>Bitburner</title>
<link rel="apple-touch-icon" sizes="180x180" href="dist/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="dist/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="dist/favicon-16x16.png">
@ -115,7 +115,7 @@
<div id="script-editor-filename-wrapper">
<p id="script-editor-filename-tag"> <strong style="background-color:#555;">Script name: </strong></p>
<input id="script-editor-filename" type="text" maxlength="100" tabindex="1" />
<input id="script-editor-filename" type="text" maxlength="100" tabindex="1"/>
</div>
<div id="ace-editor"></div>
@ -175,7 +175,7 @@
<table id="terminal">
<tr id="terminal-input">
<td id="terminal-input-td" tabindex="2">$
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;" />
<input type="text" id="terminal-input-text-box" class="terminal-input" tabindex="1" onfocus="this.value = this.value;"/>
</td>
</tr>
</table>
@ -192,7 +192,7 @@
provides information about each script's production. The scripts are categorized by the hostname of the servers on which
they are running. </p>
<p id="active-scripts-total-prod">Total online production of
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br />
Active scripts: <span class="money-gold"><span id="active-scripts-total-production-active">$0.000</span> / sec</span><br/>
Total online production since last Aug installation: <span id="active-scripts-total-prod-aug-total" class="money-gold">$0.000</span>
(<span class="money-gold"><span id="active-scripts-total-prod-aug-avg" class="money-gold">$0.000</span> / sec</span>)</p>
<ul class="active-scripts-list" id="active-scripts-list" style="list-style: none;">
@ -227,38 +227,27 @@
<!-- Tutorial content -->
<div id="tutorial-container" class="generic-menupage-container">
<h1> Tutorial (AKA Links to Documentation) </h1>
<a id="tutorial-getting-started-link" class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html" >
<a id="tutorial-getting-started-link" class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html">
Getting Started</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html">
Servers & Networking</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html">
Hacking</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html">
Scripts</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/netscript.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/netscript.html">
Netscript Programming Language</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html">
Traveling</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html">
Companies</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html">
Infiltration</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html">
Factions</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html">
Augmentations</a><br><br>
<a class="a-link-button" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
<a class="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
Keyboard Shortcuts</a>
</div>
@ -314,7 +303,7 @@
<div id="yes-no-text-input-box-container" class="popup-box-container">
<div id="yes-no-text-input-box-content" class="popup-box-content">
<p id="yes-no-text-input-box-text"> </p>
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30" />
<input type="text" id="yes-no-text-input-box-input" pattern="[a-zA-Z0-9-_]" maxlength="30"/>
<button id="yes-no-text-input-box-yes" class="popup-box-button"> Yes </button>
<button id="yes-no-text-input-box-no" class="popup-box-button"> No </button>
</div>
@ -326,7 +315,7 @@
<p id="faction-invitation-box-text"> </p>
<p id="faction-invitation-box-message"> </p>
<p id="faction-invitation-box-warning">
Would you like to join? <br /> <br />
Would you like to join? <br/> <br/>
Warning: Joining this faction may prevent you from joining other factions during this run!
</p>
<button id="faction-invitation-box-yes" class="popup-box-button"> Yes </button>
@ -339,8 +328,8 @@
<div id="infiltration-box-content" class="popup-box-content">
<p id="infiltration-box-text"> </p>
<button id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </button> <br /><br />
<select id="infiltration-faction-select" class="dropdown"> </select> <br />
<button id="infiltration-box-sell" class="a-link-button"> Sell on Black Market </button> <br/><br/>
<select id="infiltration-faction-select" class="dropdown"> </select> <br/>
<button id="infiltration-box-faction" class="a-link-button"> Give to Faction for Reputation </button>
</div>
@ -398,7 +387,7 @@
<div id="game-options-content" class="game-options-box">
<button id="game-options-close-button">&times;</button>
<h1> Game Options </h1>
<br />
<br/>
<div id="game-options-left-panel">
<!-- Netscript execution time -->
<fieldset>
@ -410,7 +399,7 @@
</span>
</label>
<input type ="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25" />
<input type="range" max="100" min="10" step="1" name="settingsNSExecTimeRangeVal" id="settingsNSExecTimeRangeVal" value="25"/>
<em id="settingsNSExecTimeRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -424,7 +413,7 @@
</span>
</label>
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50" />
<input type="range" max="100" min="20" step="1" name="settingsNSLogRangeVal" id="settingsNSLogRangeVal" value="50"/>
<em id="settingsNSLogRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -438,7 +427,7 @@
</span>
</label>
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50" />
<input type="range" max="100" min="20" step="1" name="settingsNSPortRangeVal" id="settingsNSPortRangeVal" value="50"/>
<em id="settingsNSPortRangeValLabel" style="font-style: normal;"></em>
</fieldset>
@ -450,7 +439,7 @@
</span>
</label>
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60" />
<input type="range" max="600" min="0" step="1" name="settingsAutosaveIntervalVal" id="settingsAutosaveIntervalVal" value="60"/>
<em id="settingsAutosaveIntervalValLabel" style="font-style: normal;"></em>
</fieldset>
@ -562,7 +551,7 @@
<button id="save-game-link" class="a-link-button"> Save Game </button>
<button id="delete-game-link" class="a-link-button"> Delete Game </button>
<button id="export-game-link" class="a-link-button"> Export Game </button>
<input type="file" id="import-game-file-selector" name="file" />
<input type="file" id="import-game-file-selector" name="file"/>
<button id="import-game-link" class="a-link-button"> Import Game </button>
<button id="copy-save-to-clipboard-link" class="std-button">
Copy Save data to Clipboard

@ -119,5 +119,5 @@
"watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development"
},
"version": "0.46.2"
"version": "0.47.0"
}

@ -6,7 +6,7 @@
import { IMap } from "./types";
export let CONSTANTS: IMap<any> = {
Version: "0.46.3",
Version: "0.47.0",
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
* and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then

@ -279,7 +279,7 @@ export class FactionRoot extends React.Component<IProps, IState> {
{
canPurchaseSleeves &&
<Option
buttonText={"Purchase Duplicate Sleeves"}
buttonText={"Purchase & Upgrade Duplicate Sleeves"}
infoText={sleevePurchasesInfo}
onClick={this.sleevePurchases}
/>

@ -72,7 +72,7 @@ export function purchaseHacknet() {
if (!Player.canAfford(cost)) { return -1; }
Player.loseMoney(cost);
const server = Player.createHacknetServer();
Player.hashManager.updateCapacity(Player.hacknetNodes);
updateHashManagerCapacity();
return numOwned;
} else {
@ -372,6 +372,8 @@ export function purchaseCacheUpgrade(node, levels=1) {
Player.loseMoney(cost);
node.upgradeCache(sanitizedLevels);
return true;
}
// Create/Refresh Hacknet Nodes UI

@ -125,7 +125,7 @@ function executeOrder(order: Order, refs: IProcessOrderRefs) {
// 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 firstShares = Math.min(order.shares, isLong ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown);
// First transaction to trigger movement
let res = (isLong ? buyStock(stock, firstShares, null, opts) : shortStock(stock, firstShares, null, opts));
@ -173,7 +173,7 @@ function executeOrder(order: Order, refs: IProcessOrderRefs) {
if (totalShares === 0) {
return; // Player has no shares
}
const firstShares = Math.min(totalShares, stock.shareTxUntilMovement);
const firstShares = Math.min(totalShares, isLong ? stock.shareTxUntilMovementDown : stock.shareTxUntilMovementUp);
// First transaction to trigger movement
if (isLong ? sellStock(stock, firstShares, null, opts) : sellShort(stock, firstShares, null, opts)) {

@ -138,8 +138,10 @@ export class Stock {
/**
* How many share transactions remaining until a price movement occurs
* (separately tracked for upward and downward movements)
*/
shareTxUntilMovement: number;
shareTxUntilMovementDown: number;
shareTxUntilMovementUp: number;
/**
* Spread percentage. The bid/ask prices for this stock are N% above or below
@ -160,22 +162,23 @@ export class Stock {
readonly totalShares: number;
constructor(p: IConstructorParams = defaultConstructorParams) {
this.name = p.name;
this.symbol = p.symbol;
this.price = toNumber(p.initPrice);
this.lastPrice = this.price;
this.playerShares = 0;
this.playerAvgPx = 0;
this.playerShortShares = 0;
this.playerAvgShortPx = 0;
this.mv = toNumber(p.mv);
this.b = p.b;
this.otlkMag = p.otlkMag;
this.cap = getRandomInt(this.price * 1e3, this.price * 25e3);
this.spreadPerc = toNumber(p.spreadPerc);
this.priceMovementPerc = this.spreadPerc / (getRandomInt(10, 30) / 10);
this.shareTxForMovement = toNumber(p.shareTxForMovement);
this.shareTxUntilMovement = this.shareTxForMovement;
this.name = p.name;
this.symbol = p.symbol;
this.price = toNumber(p.initPrice);
this.lastPrice = this.price;
this.playerShares = 0;
this.playerAvgPx = 0;
this.playerShortShares = 0;
this.playerAvgShortPx = 0;
this.mv = toNumber(p.mv);
this.b = p.b;
this.otlkMag = p.otlkMag;
this.cap = getRandomInt(this.price * 1e3, this.price * 25e3);
this.spreadPerc = toNumber(p.spreadPerc);
this.priceMovementPerc = this.spreadPerc / (getRandomInt(10, 30) / 10);
this.shareTxForMovement = toNumber(p.shareTxForMovement);
this.shareTxUntilMovementDown = this.shareTxForMovement;
this.shareTxUntilMovementUp = this.shareTxForMovement;
// Total shares is determined by market cap, and is rounded to nearest 100k
let totalSharesUnrounded: number = (p.marketCap / this.price);

@ -202,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.15; }
if (stock.otlkMag < 8) { stock.otlkMag += 0.1; }
}
}
}
@ -279,7 +279,8 @@ export function processStockPrices(numCycles=1) {
}
// Shares required for price movement gradually approaches max over time
stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovement + 5, stock.shareTxForMovement);
stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovementUp + 5, stock.shareTxForMovement);
stock.shareTxUntilMovement = Math.min(stock.shareTxUntilMovementDown + 5, stock.shareTxForMovement);
}
displayStockMarketContent();

@ -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.05;
export const forecastChangePerPriceMovement = 0.1;
/**
* Given a stock, calculates the amount by which the stock price is multiplied
@ -49,21 +49,24 @@ export function getBuyTransactionCost(stock: Stock, shares: number, posType: Pos
const isLong = (posType === PositionTypes.Long);
// If the number of shares doesn't trigger a price movement, its a simple calculation
if (shares <= stock.shareTxUntilMovement) {
if (isLong) {
if (isLong) {
if (shares <= stock.shareTxUntilMovementUp) {
return (shares * stock.getAskPrice()) + CONSTANTS.StockMarketCommission;
} else {
}
} else {
if (shares <= stock.shareTxUntilMovementDown) {
return (shares * stock.getBidPrice()) + CONSTANTS.StockMarketCommission;
}
}
// Calculate how many iterations of price changes we need to account for
let remainingShares = shares - stock.shareTxUntilMovement;
const firstShares = isLong ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown;
let remainingShares = shares - firstShares;
let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);
// The initial cost calculation takes care of the first "iteration"
let currPrice = isLong ? stock.getAskPrice() : stock.getBidPrice();
let totalCost = (stock.shareTxUntilMovement * currPrice);
let totalCost = (firstShares * currPrice);
const increasingMvmt = calculateIncreasingPriceMovement(stock)!;
const decreasingMvmt = calculateDecreasingPriceMovement(stock)!;
@ -111,42 +114,66 @@ export function processBuyTransactionPriceMovement(stock: Stock, shares: number,
}
}
// No price/forecast movement
if (shares <= stock.shareTxUntilMovement) {
stock.shareTxUntilMovement -= shares;
if (stock.shareTxUntilMovement <= 0) {
stock.shareTxUntilMovement = stock.shareTxForMovement;
// If there's only going to be one iteration
const firstShares = isLong ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown;
if (shares <= firstShares) {
function triggerMovement() {
processPriceMovement();
stock.changePrice(currPrice);
stock.otlkMag -= (forecastChangePerPriceMovement);
}
if (isLong) {
stock.shareTxUntilMovementUp -= shares;
if (stock.shareTxUntilMovementUp <= 0) {
stock.shareTxUntilMovementUp = stock.shareTxForMovement;
triggerMovement();
}
} else {
stock.shareTxUntilMovementDown -= shares;
if (stock.shareTxUntilMovementDown <= 0) {
stock.shareTxUntilMovementDown = stock.shareTxForMovement;
triggerMovement();
}
}
return;
}
// Calculate how many iterations of price changes we need to account for
let remainingShares = shares - stock.shareTxUntilMovement;
let remainingShares = shares - firstShares;
let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);
for (let i = 1; i < numIterations; ++i) {
processPriceMovement();
}
stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);
if (stock.shareTxUntilMovement === stock.shareTxForMovement || stock.shareTxUntilMovement <= 0) {
// The shareTxUntilMovement ended up at 0 at the end of the "processing"
++numIterations;
stock.shareTxUntilMovement = stock.shareTxForMovement;
processPriceMovement();
// If on the offchance we end up perfectly at the next price movement
if (isLong) {
stock.shareTxUntilMovementUp = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovementUp) % stock.shareTxForMovement);
if (stock.shareTxUntilMovementUp === stock.shareTxForMovement || stock.shareTxUntilMovementUp <= 0) {
// The shareTxUntilMovementUp ended up at 0 at the end of the "processing"
++numIterations;
stock.shareTxUntilMovementUp = stock.shareTxForMovement;
processPriceMovement();
}
} else {
stock.shareTxUntilMovementDown = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovementDown) % stock.shareTxForMovement);
if (stock.shareTxUntilMovementDown === stock.shareTxForMovement || stock.shareTxUntilMovementDown <= 0) {
// The shareTxUntilMovementDown ended up at 0 at the end of the "processing"
++numIterations;
stock.shareTxUntilMovementDown = stock.shareTxForMovement;
processPriceMovement();
}
}
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);
if (stock.otlkMag < 0.1) {
stock.otlkMag = 0.1;
}
}
@ -166,9 +193,10 @@ export function getSellTransactionGain(stock: Stock, shares: number, posType: Po
shares = Math.min(shares, stock.maxShares);
const isLong = (posType === PositionTypes.Long);
const firstShares = isLong ? stock.shareTxUntilMovementDown : stock.shareTxUntilMovementUp;
// If the number of shares doesn't trigger a price mvoement, its a simple calculation
if (shares <= stock.shareTxUntilMovement) {
if (shares <= firstShares) {
if (isLong) {
return (shares * stock.getBidPrice()) - CONSTANTS.StockMarketCommission;
} else {
@ -181,7 +209,7 @@ export function getSellTransactionGain(stock: Stock, shares: number, posType: Po
}
// Calculate how many iterations of price changes we need to account for
let remainingShares = shares - stock.shareTxUntilMovement;
let remainingShares = shares - firstShares;
let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);
// Helper function to calculate gain for a single iteration
@ -198,7 +226,7 @@ export function getSellTransactionGain(stock: Stock, shares: number, posType: Po
// The initial cost calculation takes care of the first "iteration"
let currPrice = isLong ? stock.getBidPrice() : stock.getAskPrice();
let totalGain = calculateGain(currPrice, stock.shareTxUntilMovement);
let totalGain = calculateGain(currPrice, firstShares);
for (let i = 1; i < numIterations; ++i) {
// Price movement
if (isLong) {
@ -229,6 +257,7 @@ export function processSellTransactionPriceMovement(stock: Stock, shares: number
shares = Math.min(shares, stock.maxShares);
const isLong = (posType === PositionTypes.Long);
const firstShares = isLong ? stock.shareTxUntilMovementDown : stock.shareTxUntilMovementUp;
let currPrice = stock.price;
function processPriceMovement() {
@ -239,41 +268,64 @@ export function processSellTransactionPriceMovement(stock: Stock, shares: number
}
}
// No price/forecast movement
if (shares <= stock.shareTxUntilMovement) {
stock.shareTxUntilMovement -= shares;
if (stock.shareTxUntilMovement <= 0) {
stock.shareTxUntilMovement = stock.shareTxForMovement;
// If there's only going to be one iteration at most
if (shares <= firstShares) {
function triggerPriceMovement() {
processPriceMovement();
stock.changePrice(currPrice);
stock.otlkMag -= (forecastChangePerPriceMovement);
}
if (isLong) {
stock.shareTxUntilMovementDown -= shares;
if (stock.shareTxUntilMovementDown <= 0) {
stock.shareTxUntilMovementDown = stock.shareTxForMovement;
triggerPriceMovement();
}
} else {
stock.shareTxUntilMovementUp -= shares;
if (stock.shareTxUntilMovementUp <= 0) {
stock.shareTxUntilMovementUp = stock.shareTxForMovement;
triggerPriceMovement();
}
}
return;
}
// Calculate how many iterations of price changes we need to account for
let remainingShares = shares - stock.shareTxUntilMovement;
let remainingShares = shares - firstShares;
let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);
for (let i = 1; i < numIterations; ++i) {
processPriceMovement();
}
stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);
if (stock.shareTxUntilMovement === stock.shareTxForMovement || stock.shareTxUntilMovement <= 0) {
++numIterations;
stock.shareTxUntilMovement = stock.shareTxForMovement;
processPriceMovement();
// If on the offchance we end up perfectly at the next price movement
if (isLong) {
stock.shareTxUntilMovementDown = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovementDown) % stock.shareTxForMovement);
if (stock.shareTxUntilMovementDown === stock.shareTxForMovement || stock.shareTxUntilMovementDown <= 0) {
++numIterations;
stock.shareTxUntilMovementDown = stock.shareTxForMovement;
processPriceMovement();
}
} else {
stock.shareTxUntilMovementUp = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovementUp) % stock.shareTxForMovement);
if (stock.shareTxUntilMovementUp === stock.shareTxForMovement || stock.shareTxUntilMovementUp <= 0) {
++numIterations;
stock.shareTxUntilMovementUp = stock.shareTxForMovement;
processPriceMovement();
}
}
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);
if (stock.otlkMag < 0.1) {
stock.otlkMag = 0.1;
}
}
@ -299,14 +351,15 @@ export function calculateBuyMaxAmount(stock: Stock, posType: PositionTypes, mone
let currPrice = isLong ? stock.getAskPrice() : stock.getBidPrice();
// No price movement
const firstIterationCost = stock.shareTxUntilMovement * currPrice;
const firstShares = isLong ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown;
const firstIterationCost = firstShares * currPrice;
if (remainingMoney < firstIterationCost) {
return Math.floor(remainingMoney / currPrice);
}
// We'll avoid any accidental infinite loops by having a hardcoded maximum number of
// iterations
let numShares = stock.shareTxUntilMovement;
let numShares = firstShares;
remainingMoney -= firstIterationCost;
for (let i = 0; i < 10e3; ++i) {
if (isLong) {

@ -48,6 +48,7 @@ type IProps = {
orders: Order[];
p: IPlayer;
placeOrder: placeOrderFn;
rerenderAllTickers: () => void;
sellStockLong: txFn;
sellStockShort: txFn;
stock: Stock;
@ -57,7 +58,6 @@ type IState = {
orderType: SelectorOrderType;
position: PositionTypes;
qty: string;
rerenderFlag: boolean;
}
export class StockTicker extends React.Component<IProps, IState> {
@ -68,7 +68,6 @@ export class StockTicker extends React.Component<IProps, IState> {
orderType: SelectorOrderType.Market,
position: PositionTypes.Long,
qty: "",
rerenderFlag: false,
}
this.getBuyTransactionCostText = this.getBuyTransactionCostText.bind(this);
@ -81,7 +80,6 @@ export class StockTicker extends React.Component<IProps, IState> {
this.handleQuantityChange = this.handleQuantityChange.bind(this);
this.handleSellButtonClick = this.handleSellButtonClick.bind(this);
this.handleSellAllButtonClick = this.handleSellAllButtonClick.bind(this);
this.rerender = this.rerender.bind(this);
}
createPlaceOrderPopupBox(yesTxt: string, popupTxt: string, yesBtnCb: (price: number) => void) {
@ -119,7 +117,8 @@ export class StockTicker extends React.Component<IProps, IState> {
let costTxt = `Purchasing ${numeralWrapper.formatBigNumber(qty)} shares (${this.state.position === PositionTypes.Long ? "Long" : "Short"}) ` +
`will cost ${numeralWrapper.formatMoney(cost)}. `;
const causesMovement = qty > stock.shareTxUntilMovement;
const amtNeededForMovement = this.state.position === PositionTypes.Long ? stock.shareTxUntilMovementUp : stock.shareTxUntilMovementDown;
const causesMovement = qty > amtNeededForMovement;
if (causesMovement) {
costTxt += `WARNING: Purchasing this many shares will influence the stock price`;
}
@ -152,7 +151,8 @@ export class StockTicker extends React.Component<IProps, IState> {
let costTxt = `Selling ${numeralWrapper.formatBigNumber(qty)} shares (${this.state.position === PositionTypes.Long ? "Long" : "Short"}) ` +
`will result in a gain of ${numeralWrapper.formatMoney(cost)}. `;
const causesMovement = qty > stock.shareTxUntilMovement;
const amtNeededForMovement = this.state.position === PositionTypes.Long ? stock.shareTxUntilMovementDown : stock.shareTxUntilMovementUp;
const causesMovement = qty > amtNeededForMovement;
if (causesMovement) {
costTxt += `WARNING: Selling this many shares will influence the stock price`;
}
@ -174,7 +174,7 @@ export class StockTicker extends React.Component<IProps, IState> {
} else {
this.props.buyStockLong(this.props.stock, shares);
}
this.rerender();
this.props.rerenderAllTickers();
break;
}
case SelectorOrderType.Limit: {
@ -216,7 +216,7 @@ export class StockTicker extends React.Component<IProps, IState> {
} else {
this.props.buyStockLong(stock, maxShares);
}
this.rerender();
this.props.rerenderAllTickers();
break;
}
default: {
@ -297,7 +297,7 @@ export class StockTicker extends React.Component<IProps, IState> {
} else {
this.props.sellStockLong(this.props.stock, shares);
}
this.rerender();
this.props.rerenderAllTickers();
break;
}
case SelectorOrderType.Limit: {
@ -335,7 +335,7 @@ export class StockTicker extends React.Component<IProps, IState> {
} else {
this.props.sellStockLong(stock, stock.playerShares);
}
this.rerender();
this.props.rerenderAllTickers();
break;
}
default: {
@ -355,20 +355,12 @@ export class StockTicker extends React.Component<IProps, IState> {
return (this.props.p.bitNodeN === 8 || (SourceFileFlags[8] >= 2));
}
rerender(): void {
this.setState((prevState) => {
return {
rerenderFlag: !prevState.rerenderFlag,
}
});
}
render() {
// Determine if the player's intended transaction will cause a price movement
let causesMovement: boolean = false;
const qty = this.getQuantity();
if (!isNaN(qty)) {
causesMovement = qty > this.props.stock.shareTxUntilMovement;
causesMovement = qty > this.props.stock.shareTxForMovement;
}
return (
@ -411,7 +403,7 @@ export class StockTicker extends React.Component<IProps, IState> {
{
causesMovement &&
<p className="stock-market-price-movement-warning">
WARNING: Buying/Selling {numeralWrapper.formatBigNumber(qty)} shares will affect
WARNING: Buying/Selling {numeralWrapper.formatBigNumber(qty)} shares may affect
the stock's price. This applies during the transaction itself as well. See Investopedia
for more details.
</p>

@ -53,6 +53,7 @@ export class StockTickers extends React.Component<IProps, IState> {
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();
}
@ -159,6 +160,7 @@ export class StockTickers extends React.Component<IProps, IState> {
orders={orders}
p={this.props.p}
placeOrder={this.props.placeOrder}
rerenderAllTickers={this.rerender}
sellStockLong={this.props.sellStockLong}
sellStockShort={this.props.sellStockShort}
stock={val}

@ -52,16 +52,17 @@ export function displayCharacterInfo(elem: HTMLElement, p: IPlayer) {
function convertMoneySourceTrackerToString(src: MoneySourceTracker): string {
let parts: string[] = [`Total: ${numeralWrapper.formatMoney(src.total)}`];
if (src.bladeburner) { parts.push(`Bladeburner: ${numeralWrapper.formatMoney(src.bladeburner)}`) };
if (src.codingcontract) { parts.push(`Coding Contracts: ${numeralWrapper.formatMoney(src.codingcontract)}`) };
if (src.work) { parts.push(`Company Work: ${numeralWrapper.formatMoney(src.work)}`) };
if (src.corporation) { parts.push(`Corporation: ${numeralWrapper.formatMoney(src.corporation)}`) };
if (src.crime) { parts.push(`Crimes: ${numeralWrapper.formatMoney(src.crime)}`) };
if (src.gang) { parts.push(`Gang: ${numeralWrapper.formatMoney(src.gang)}`) };
if (src.hacking) { parts.push(`Hacking: ${numeralWrapper.formatMoney(src.hacking)}`) };
if (src.hacknetnode) { parts.push(`Hacknet Nodes: ${numeralWrapper.formatMoney(src.hacknetnode)}`) };
if (src.infiltration) { parts.push(`Infiltration: ${numeralWrapper.formatMoney(src.infiltration)}`) };
if (src.stock) { parts.push(`Stock Market: ${numeralWrapper.formatMoney(src.stock)}`) };
if (src.bladeburner) { parts.push(`Bladeburner: ${numeralWrapper.formatMoney(src.bladeburner)}`) };
if (src.codingcontract) { parts.push(`Coding Contracts: ${numeralWrapper.formatMoney(src.codingcontract)}`) };
if (src.work) { parts.push(`Company Work: ${numeralWrapper.formatMoney(src.work)}`) };
if (src.corporation) { parts.push(`Corporation: ${numeralWrapper.formatMoney(src.corporation)}`) };
if (src.crime) { parts.push(`Crimes: ${numeralWrapper.formatMoney(src.crime)}`) };
if (src.gang) { parts.push(`Gang: ${numeralWrapper.formatMoney(src.gang)}`) };
if (src.hacking) { parts.push(`Hacking: ${numeralWrapper.formatMoney(src.hacking)}`) };
if (src.hacknetnode) { parts.push(`Hacknet Nodes: ${numeralWrapper.formatMoney(src.hacknetnode)}`) };
if (src.hospitalization) { parts.push(`Hospitalization: ${numeralWrapper.formatMoney(src.hospitalization)}`) };
if (src.infiltration) { parts.push(`Infiltration: ${numeralWrapper.formatMoney(src.infiltration)}`) };
if (src.stock) { parts.push(`Stock Market: ${numeralWrapper.formatMoney(src.stock)}`) };
return parts.join("<br>");
}

@ -79,7 +79,8 @@ describe("Stock Market Tests", function() {
expect(stock.b).to.equal(ctorParams.b);
expect(stock.mv).to.equal(ctorParams.mv);
expect(stock.shareTxForMovement).to.equal(ctorParams.shareTxForMovement);
expect(stock.shareTxUntilMovement).to.equal(ctorParams.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(ctorParams.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(ctorParams.shareTxForMovement);
expect(stock.maxShares).to.be.below(stock.totalShares);
expect(stock.spreadPerc).to.equal(ctorParams.spreadPerc);
expect(stock.priceMovementPerc).to.be.a("number");
@ -436,24 +437,24 @@ describe("Stock Market Tests", function() {
it("should do nothing on invalid 'stock' argument", function() {
const oldPrice = stock.price;
const oldTracker = stock.shareTxUntilMovement;
const oldTracker = stock.shareTxUntilMovementUp;
processBuyTransactionPriceMovement({}, mvmtShares, PositionTypes.Long);
expect(stock.price).to.equal(oldPrice);
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
expect(stock.shareTxUntilMovementUp).to.equal(oldTracker);
});
it("should do nothing on invalid 'shares' arg", function() {
const oldPrice = stock.price;
const oldTracker = stock.shareTxUntilMovement;
const oldTracker = stock.shareTxUntilMovementUp;
processBuyTransactionPriceMovement(stock, NaN, PositionTypes.Long);
expect(stock.price).to.equal(oldPrice);
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
expect(stock.shareTxUntilMovementUp).to.equal(oldTracker);
processBuyTransactionPriceMovement(stock, -1, PositionTypes.Long);
expect(stock.price).to.equal(oldPrice);
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
expect(stock.shareTxUntilMovementUp).to.equal(oldTracker);
});
it("should properly evaluate a LONG transaction that doesn't trigger a price movement", function() {
@ -463,7 +464,8 @@ describe("Stock Market Tests", function() {
processBuyTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Long);
expect(stock.price).to.equal(oldPrice);
expect(stock.otlkMag).to.equal(oldForecast);
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate a SHORT transaction that doesn't trigger a price movement", function() {
@ -473,7 +475,8 @@ describe("Stock Market Tests", function() {
processBuyTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Short);
expect(stock.price).to.equal(oldPrice);
expect(stock.otlkMag).to.equal(oldForecast);
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate LONG transactions that trigger price movements", function() {
@ -483,7 +486,7 @@ describe("Stock Market Tests", function() {
processBuyTransactionPriceMovement(stock, mvmtShares, PositionTypes.Long);
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement - noMvmtShares);
});
it("should properly evaluate SHORT transactions that trigger price movements", function() {
@ -493,7 +496,7 @@ describe("Stock Market Tests", function() {
processBuyTransactionPriceMovement(stock, mvmtShares, PositionTypes.Short);
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement - noMvmtShares);
});
it("should properly evaluate LONG transactions of exactly 'shareTxForMovement' shares", function() {
@ -503,7 +506,8 @@ describe("Stock Market Tests", function() {
processBuyTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Long);
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate LONG transactions that total to 'shareTxForMovement' shares", function() {
@ -511,10 +515,11 @@ describe("Stock Market Tests", function() {
const oldForecast = stock.otlkMag;
processBuyTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Long);
processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Long);
processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovementUp, PositionTypes.Long);
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate LONG transactions that are a multiple of 'shareTxForMovement' shares", function() {
@ -524,7 +529,8 @@ describe("Stock Market Tests", function() {
processBuyTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Long);
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate SHORT transactions of exactly 'shareTxForMovement' shares", function() {
@ -534,7 +540,8 @@ describe("Stock Market Tests", function() {
processBuyTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Short);
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate SHORT transactions that total to 'shareTxForMovement' shares", function() {
@ -542,10 +549,11 @@ describe("Stock Market Tests", function() {
const oldForecast = stock.otlkMag;
processBuyTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Short);
processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Short);
expect(stock.shareTxUntilMovementDown).to.be.below(stock.shareTxForMovement);
processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovementDown, PositionTypes.Short);
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate SHORT transactions that are a multiple of 'shareTxForMovement' shares", function() {
@ -555,7 +563,7 @@ describe("Stock Market Tests", function() {
processBuyTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Short);
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
});
@ -565,24 +573,24 @@ describe("Stock Market Tests", function() {
it("should do nothing on invalid 'stock' argument", function() {
const oldPrice = stock.price;
const oldTracker = stock.shareTxUntilMovement;
const oldTracker = stock.shareTxUntilMovementDown;
processSellTransactionPriceMovement({}, mvmtShares, PositionTypes.Long);
expect(stock.price).to.equal(oldPrice);
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
expect(stock.shareTxUntilMovementDown).to.equal(oldTracker);
});
it("should do nothing on invalid 'shares' arg", function() {
const oldPrice = stock.price;
const oldTracker = stock.shareTxUntilMovement;
const oldTracker = stock.shareTxUntilMovementDown;
processSellTransactionPriceMovement(stock, NaN, PositionTypes.Long);
expect(stock.price).to.equal(oldPrice);
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
expect(stock.shareTxUntilMovementDown).to.equal(oldTracker);
processSellTransactionPriceMovement(stock, -1, PositionTypes.Long);
expect(stock.price).to.equal(oldPrice);
expect(stock.shareTxUntilMovement).to.equal(oldTracker);
expect(stock.shareTxUntilMovementDown).to.equal(oldTracker);
});
it("should properly evaluate a LONG transaction that doesn't trigger a price movement", function() {
@ -592,7 +600,8 @@ describe("Stock Market Tests", function() {
processSellTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Long);
expect(stock.price).to.equal(oldPrice);
expect(stock.otlkMag).to.equal(oldForecast);
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate a SHORT transaction that doesn't trigger a price movement", function() {
@ -602,7 +611,8 @@ describe("Stock Market Tests", function() {
processSellTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Short);
expect(stock.price).to.equal(oldPrice);
expect(stock.otlkMag).to.equal(oldForecast);
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate LONG transactions that trigger price movements", function() {
@ -612,7 +622,8 @@ describe("Stock Market Tests", function() {
processSellTransactionPriceMovement(stock, mvmtShares, PositionTypes.Long);
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate SHORT transactions that trigger price movements", function() {
@ -622,7 +633,8 @@ describe("Stock Market Tests", function() {
processSellTransactionPriceMovement(stock, mvmtShares, PositionTypes.Short);
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement - noMvmtShares);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate LONG transactions of exactly 'shareTxForMovement' shares", function() {
@ -632,7 +644,8 @@ describe("Stock Market Tests", function() {
processSellTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Long);
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate LONG transactions that total to 'shareTxForMovement' shares", function() {
@ -640,10 +653,12 @@ describe("Stock Market Tests", function() {
const oldForecast = stock.otlkMag;
processSellTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Long);
processSellTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Long);
expect(stock.shareTxUntilMovementDown).to.be.below(stock.shareTxForMovement);
processSellTransactionPriceMovement(stock, stock.shareTxUntilMovementDown, PositionTypes.Long);
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate LONG transactions that are a multiple of 'shareTxForMovement' shares", function() {
@ -653,7 +668,8 @@ describe("Stock Market Tests", function() {
processSellTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Long);
expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate SHORT transactions of exactly 'shareTxForMovement' shares", function() {
@ -663,7 +679,8 @@ describe("Stock Market Tests", function() {
processSellTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Short);
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate SHORT transactions that total to 'shareTxForMovement' shares", function() {
@ -671,10 +688,13 @@ describe("Stock Market Tests", function() {
const oldForecast = stock.otlkMag;
processSellTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Short);
processSellTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Short);
expect(stock.shareTxUntilMovementUp).to.be.below(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
processSellTransactionPriceMovement(stock, stock.shareTxUntilMovementUp, PositionTypes.Short);
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
it("should properly evaluate SHORT transactions that are a multiple of 'shareTxForMovement' shares", function() {
@ -684,7 +704,8 @@ describe("Stock Market Tests", function() {
processSellTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Short);
expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));
expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));
expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementUp).to.equal(stock.shareTxForMovement);
expect(stock.shareTxUntilMovementDown).to.equal(stock.shareTxForMovement);
});
});
});