diff --git a/package-lock.json b/package-lock.json index 7185875bf..ddc505732 100644 --- a/package-lock.json +++ b/package-lock.json @@ -787,6 +787,16 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -933,6 +943,12 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -1084,6 +1100,16 @@ } } }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.6.5", + "regenerator-runtime": "0.11.1" + } + }, "bail": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz", @@ -1318,6 +1344,12 @@ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", "dev": true }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", @@ -1409,6 +1441,12 @@ "isarray": "1.0.0" } }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, "buffer-indexof": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", @@ -1619,6 +1657,20 @@ "lazy-cache": "1.0.4" } }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + } + }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -1670,6 +1722,12 @@ "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", "dev": true }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, "chokidar": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", @@ -2504,6 +2562,12 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "core-js": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.5.tgz", + "integrity": "sha512-klh/kDpwX8hryYL14M9w/xei6vrv6sE8gTHDG7/T/+SEovB/G4ejwcfE/CBzO6Edsu+OETZMZ3wcX/EjUkrl5A==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -2834,6 +2898,15 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", @@ -3216,6 +3289,12 @@ "minimalistic-crypto-utils": "1.0.1" } }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -4152,6 +4231,23 @@ "locate-path": "2.0.0" } }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "2.0.3" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", + "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "dev": true + } + } + }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -4395,6 +4491,12 @@ "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", "dev": true }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -4603,6 +4705,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, "handle-thing": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", @@ -6795,6 +6903,518 @@ "minimist": "0.0.8" } }, + "mocha": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.1.4.tgz", + "integrity": "sha512-PN8CIy4RXsIoxoFJzS4QNnCH4psUCPWc4/rPrst/ecSJJbLBkubMiyGCP2Kj/9YnWbotFqAoeXyXMucj7gwCFg==", + "dev": true, + "requires": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "2.2.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "ms": "2.1.1", + "node-environment-flags": "1.0.5", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.2.2", + "yargs-parser": "13.0.0", + "yargs-unparser": "1.5.0" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "2.1.1" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "6.0.5", + "get-stream": "4.1.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "3.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "3.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.1" + } + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "3.0.0", + "path-exists": "3.0.0" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "0.1.3", + "mimic-fn": "2.1.0", + "p-is-promise": "2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "1.0.0", + "lcid": "2.0.0", + "mem": "4.3.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "2.2.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "7.0.3", + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "5.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", + "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "dev": true, + "requires": { + "cliui": "4.1.0", + "find-up": "3.0.0", + "get-caller-file": "2.0.5", + "os-locale": "3.1.0", + "require-directory": "2.1.1", + "require-main-filename": "2.0.0", + "set-blocking": "2.0.0", + "string-width": "3.1.0", + "which-module": "2.0.0", + "y18n": "4.0.0", + "yargs-parser": "13.0.0" + } + }, + "yargs-parser": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", + "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "dev": true, + "requires": { + "camelcase": "5.3.1", + "decamelize": "1.2.0" + } + } + } + }, + "mochapack": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/mochapack/-/mochapack-1.1.1.tgz", + "integrity": "sha512-t8WchR4+38f0BO7+nBcUexqe1NNhzr8vsylOp5wF/J1EWP47T76KRVnZIrHHjxXdnp5JJHZtUD8C0pkJG2iv0g==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "chalk": "2.4.2", + "chokidar": "2.1.5", + "glob-parent": "3.1.0", + "globby": "7.1.1", + "interpret": "1.1.0", + "is-glob": "4.0.0", + "loader-utils": "1.1.0", + "lodash": "4.17.10", + "memory-fs": "0.4.1", + "nodent-runtime": "3.2.1", + "normalize-path": "2.1.1", + "progress": "2.0.0", + "source-map-support": "0.5.12", + "strip-ansi": "4.0.0", + "toposort": "1.0.7", + "yargs": "11.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "chokidar": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz", + "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "3.0.0", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1", + "upath": "1.1.2" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "glob": "7.1.3", + "ignore": "3.3.7", + "pify": "3.0.0", + "slash": "1.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "micromatch": "3.1.10", + "readable-stream": "2.3.4" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "upath": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", + "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", + "dev": true + } + } + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -6922,6 +7542,24 @@ "lower-case": "1.1.4" } }, + "node-environment-flags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", + "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "2.0.3", + "semver": "5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", + "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", + "dev": true + } + } + }, "node-forge": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", @@ -7054,6 +7692,12 @@ } } }, + "nodent-runtime": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/nodent-runtime/-/nodent-runtime-3.2.1.tgz", + "integrity": "sha512-7Ws63oC+215smeKJQCxzrK21VFVlCFBkwl0MOObt0HOpVQXs3u483sAmtkF33nNqZ5rSOQjB76fgyPBmAUrtCA==", + "dev": true + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -7624,6 +8268,12 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", "dev": true }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, "pbkdf2": { "version": "3.0.16", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", @@ -8896,6 +9546,12 @@ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", "dev": true }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", @@ -10244,6 +10900,24 @@ "urix": "0.1.0" } }, + "source-map-support": { + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", + "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "dev": true, + "requires": { + "buffer-from": "1.1.1", + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", @@ -13255,6 +13929,220 @@ "dev": true } } + }, + "yargs-unparser": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", + "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", + "dev": true, + "requires": { + "flat": "4.1.0", + "lodash": "4.17.11", + "yargs": "12.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "6.0.5", + "get-stream": "4.1.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "3.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "2.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "3.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "0.1.3", + "mimic-fn": "2.1.0", + "p-is-promise": "2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "1.0.0", + "lcid": "2.0.0", + "mem": "4.3.0" + } + }, + "p-limit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", + "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "dev": true, + "requires": { + "p-try": "2.2.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "3.0.0", + "get-caller-file": "1.0.2", + "os-locale": "3.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "5.3.1", + "decamelize": "1.2.0" + } + } + } } } } diff --git a/package.json b/package.json index 1860add86..c896b1eae 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "beautify-lint": "^1.0.3", "benchmark": "^2.1.1", "bundle-loader": "~0.5.0", + "chai": "^4.2.0", "css-loader": "^0.28.11", "es6-promise-polyfill": "^1.1.1", "eslint": "^4.19.1", @@ -64,6 +65,8 @@ "lodash": "^4.17.10", "mini-css-extract-plugin": "^0.4.1", "mkdirp": "^0.5.1", + "mocha": "^6.1.4", + "mochapack": "^1.1.1", "node-sass": "^4.10.0", "raw-loader": "~0.5.0", "sass-loader": "^7.0.3", @@ -108,6 +111,7 @@ "lint:style": "stylelint ./css/*", "lint:typescript": "tslint --project . --exclude **/*.d.ts --format stylish src/**/*.ts utils/**/*.ts", "preinstall": "node ./scripts/engines-check.js", + "test": "mochapack --webpack-config webpack.config-test.js ./test/index.js", "watch": "webpack --watch --mode production", "watch:dev": "webpack --watch --mode development" }, diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index 93b12426f..0b1ae2bf8 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -260,7 +260,7 @@ export const RamCosts: IMap = { getStamina: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost, joinBladeburnerFaction: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost, joinBladeburnerDivision: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getBonusTime: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost, + getBonusTime: () => 0, }, // Coding Contract API @@ -327,6 +327,6 @@ export function getRamCost(...args: string[]): number { return curr; } - console.warn(`Expected type: ${currType}`); + console.warn(`Unexpected type (${currType}) for value [${args}]`); return 0; } diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index f785c5e2e..58b9ca56e 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -107,7 +107,7 @@ import { OrderTypes } from "./StockMarket/data/OrderTypes"; import { PositionTypes } from "./StockMarket/data/PositionTypes"; import { StockSymbols } from "./StockMarket/data/StockSymbols"; import { - getStockmarket4SDataCost, + getStockMarket4SDataCost, getStockMarket4STixApiCost } from "./StockMarket/StockMarketCosts"; import { TextFile, getTextFile, createTextFile } from "./TextFile"; diff --git a/test/Netscript/DynamicRamCalculationTests.js b/test/Netscript/DynamicRamCalculationTests.js new file mode 100644 index 000000000..edaf2360e --- /dev/null +++ b/test/Netscript/DynamicRamCalculationTests.js @@ -0,0 +1,11 @@ +// TODO Importing NetscriptFunctions breaks the mochapack build +// import { NetscriptFunctions } from "../../src/NetscriptFunctions"; +import { expect } from "chai"; + +console.log("Beginning Netscript Dynamic RAM Calculation/Generation Tests"); + +describe("Netscript Static RAM Calculation/Generation Tests", function() { + it("should run", function() { + expect(1).to.equal(1); + }); +}); diff --git a/test/Netscript/StaticRamCalculationTests.js b/test/Netscript/StaticRamCalculationTests.js index 51b5d3236..b00887694 100644 --- a/test/Netscript/StaticRamCalculationTests.js +++ b/test/Netscript/StaticRamCalculationTests.js @@ -1,17 +1,1115 @@ -/** - * 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; +import { getRamCost, RamCostConstants } from "../../src/Netscript/RamCostGenerator"; +import { calculateRamUsage } from "../../src/Script/RamCalculations" +import { expect } from "chai"; console.log("Beginning Netscript Static RAM Calculation/Generation Tests"); -describe("Netscript Static RAM Calculation/Generation Tests", function() { +const ScriptBaseCost = RamCostConstants.ScriptBaseRamCost; +const HacknetNamespaceCost = RamCostConstants.ScriptHacknetNodesRamCost; +describe("Netscript Static RAM Calculation/Generation Tests", function() { + // Tests numeric equality, allowing for floating point imprecision + function testEquality(val, expected) { + expect(val).to.be.within(expected - 10 * Number.EPSILON, expected + 10 * Number.EPSILON); + } + + /** + * Tests that: + * 1. A function has non-zero RAM cost + * 2. The calculator and the generator result in equal values + * 3. Running multiple calls of the function does not result in additional RAM cost + * @param {string[]} fnDesc - describes the name of the function being tested, + * including the namespace(s). e.g. ["gang", "getMemberNames"] + */ + async function expectNonZeroRamCost(fnDesc) { + if (!Array.isArray(fnDesc)) { expect.fail("Non-array passed to expectNonZeroRamCost()"); } + const expected = getRamCost(...fnDesc); + expect(expected).to.be.above(0); + + const code = fnDesc.join(".") + "(); "; + + const calculated = await calculateRamUsage(code, []); + testEquality(calculated, expected + ScriptBaseCost); + + const multipleCallsCode = code.repeat(3); + const multipleCallsCalculated = await calculateRamUsage(multipleCallsCode, []); + expect(multipleCallsCalculated).to.equal(calculated); + } + + /** + * Tests that: + * 1. A function has zero RAM cost + * 2. The calculator and the generator result in equal values + * 3. Running multiple calls of the function does not result in additional RAM cost + * @param {string[]} fnDesc - describes the name of the function being tested, + * including the namespace(s). e.g. ["gang", "getMemberNames"] + */ + async function expectZeroRamCost(fnDesc) { + if (!Array.isArray(fnDesc)) { expect.fail("Non-array passed to expectZeroRamCost()"); } + const expected = getRamCost(...fnDesc); + expect(expected).to.equal(0); + + const code = fnDesc.join(".") + "(); "; + + const calculated = await calculateRamUsage(code, []); + testEquality(calculated, ScriptBaseCost); + + const multipleCallsCode = code.repeat(3); + const multipleCallsCalculated = await calculateRamUsage(code, []); + expect(multipleCallsCalculated).to.equal(ScriptBaseCost); + } + + describe("Basic Functions", async function() { + it("hack()", async function() { + const f = ["hack"]; + await expectNonZeroRamCost(f); + }); + + it("grow()", async function() { + const f = ["grow"]; + await expectNonZeroRamCost(f); + }); + + it("weaken()", async function() { + const f = ["weaken"]; + await expectNonZeroRamCost(f); + }); + + it("hackAnalyzeThreads()", async function() { + const f = ["hackAnalyzeThreads"]; + await expectNonZeroRamCost(f); + }); + + it("hackAnalyzePercent()", async function() { + const f = ["hackAnalyzePercent"]; + await expectNonZeroRamCost(f); + }); + + it("hackChance()", async function() { + const f = ["hackChance"]; + await expectNonZeroRamCost(f); + }); + + it("growthAnalyze()", async function() { + const f = ["growthAnalyze"]; + await expectNonZeroRamCost(f); + }); + + it("sleep()", async function() { + const f = ["sleep"]; + await expectZeroRamCost(f); + }); + + it("print()", async function() { + const f = ["print"]; + await expectZeroRamCost(f); + }); + + it("tprint()", async function() { + const f = ["tprint"]; + await expectZeroRamCost(f); + }); + + it("clearLog()", async function() { + const f = ["clearLog"]; + await expectZeroRamCost(f); + }); + + it("disableLog()", async function() { + const f = ["disableLog"]; + await expectZeroRamCost(f); + }); + + it("enableLog()", async function() { + const f = ["enableLog"]; + await expectZeroRamCost(f); + }); + + it("isLogEnabled()", async function() { + const f = ["isLogEnabled"]; + await expectZeroRamCost(f); + }); + + it("getScriptLogs()", async function() { + const f = ["getScriptLogs"]; + await expectZeroRamCost(f); + }); + + it("scan()", async function() { + const f = ["scan"]; + await expectNonZeroRamCost(f); + }); + + it("nuke()", async function() { + const f = ["nuke"]; + await expectNonZeroRamCost(f); + }); + + it("brutessh()", async function() { + const f = ["brutessh"]; + await expectNonZeroRamCost(f); + }); + + it("ftpcrack()", async function() { + const f = ["ftpcrack"]; + await expectNonZeroRamCost(f); + }); + + it("relaysmtp()", async function() { + const f = ["relaysmtp"]; + await expectNonZeroRamCost(f); + }); + + it("httpworm()", async function() { + const f = ["httpworm"]; + await expectNonZeroRamCost(f); + }); + + it("sqlinject()", async function() { + const f = ["sqlinject"]; + await expectNonZeroRamCost(f); + }); + + it("run()", async function() { + const f = ["run"]; + await expectNonZeroRamCost(f); + }); + + it("exec()", async function() { + const f = ["exec"]; + await expectNonZeroRamCost(f); + }); + + it("spawn()", async function() { + const f = ["spawn"]; + await expectNonZeroRamCost(f); + }); + + it("kill()", async function() { + const f = ["kill"]; + await expectNonZeroRamCost(f); + }); + + it("killall()", async function() { + const f = ["killall"]; + await expectNonZeroRamCost(f); + }); + + it("exit()", async function() { + const f = ["exit"]; + await expectZeroRamCost(f); + }); + + it("scp()", async function() { + const f = ["scp"]; + await expectNonZeroRamCost(f); + }); + + it("ls()", async function() { + const f = ["ls"]; + await expectNonZeroRamCost(f); + }); + + it("ps()", async function() { + const f = ["ps"]; + await expectNonZeroRamCost(f); + }); + + it("hasRootAccess()", async function() { + const f = ["hasRootAccess"]; + await expectNonZeroRamCost(f); + }); + + it("getHostname()", async function() { + const f = ["getHostname"]; + await expectNonZeroRamCost(f); + }); + + it("getHackingLevel()", async function() { + const f = ["getHackingLevel"]; + await expectNonZeroRamCost(f); + }); + + it("getHackingMultipliers()", async function() { + const f = ["getHackingMultipliers"]; + await expectNonZeroRamCost(f); + }); + + it("getHacknetMultipliers()", async function() { + const f = ["getHacknetMultipliers"]; + await expectNonZeroRamCost(f); + }); + + it("getServerMoneyAvailable()", async function() { + const f = ["getServerMoneyAvailable"]; + await expectNonZeroRamCost(f); + }); + + it("getServerMaxMoney()", async function() { + const f = ["getServerMaxMoney"]; + await expectNonZeroRamCost(f); + }); + + it("getServerGrowth()", async function() { + const f = ["getServerGrowth"]; + await expectNonZeroRamCost(f); + }); + + it("getServerSecurityLevel()", async function() { + const f = ["getServerSecurityLevel"]; + await expectNonZeroRamCost(f); + }); + + it("getServerBaseSecurityLevel()", async function() { + const f = ["getServerBaseSecurityLevel"]; + await expectNonZeroRamCost(f); + }); + + it("getServerMinSecurityLevel()", async function() { + const f = ["getServerMinSecurityLevel"]; + await expectNonZeroRamCost(f); + }); + + it("getServerRequiredHackingLevel()", async function() { + const f = ["getServerRequiredHackingLevel"]; + await expectNonZeroRamCost(f); + }); + + it("getServerNumPortsRequired()", async function() { + const f = ["getServerNumPortsRequired"]; + await expectNonZeroRamCost(f); + }); + + it("getServerRam()", async function() { + const f = ["getServerRam"]; + await expectNonZeroRamCost(f); + }); + + it("serverExists()", async function() { + const f = ["serverExists"]; + await expectNonZeroRamCost(f); + }); + + it("fileExists()", async function() { + const f = ["fileExists"]; + await expectNonZeroRamCost(f); + }); + + it("isRunning()", async function() { + const f = ["isRunning"]; + await expectNonZeroRamCost(f); + }); + + it("getPurchasedServerCost()", async function() { + const f = ["getPurchasedServerCost"]; + await expectNonZeroRamCost(f); + }); + + it("purchaseServer()", async function() { + const f = ["purchaseServer"]; + await expectNonZeroRamCost(f); + }); + + it("deleteServer()", async function() { + const f = ["deleteServer"]; + await expectNonZeroRamCost(f); + }); + + it("getPurchasedServers()", async function() { + const f = ["getPurchasedServers"]; + await expectNonZeroRamCost(f); + }); + + it("getPurchasedServerLimit()", async function() { + const f = ["getPurchasedServerLimit"]; + await expectNonZeroRamCost(f); + }); + + it("getPurchasedServerMaxRam()", async function() { + const f = ["getPurchasedServerMaxRam"]; + await expectNonZeroRamCost(f); + }); + + it("write()", async function() { + const f = ["write"]; + await expectNonZeroRamCost(f); + }); + + it("tryWrite()", async function() { + const f = ["tryWrite"]; + await expectNonZeroRamCost(f); + }); + + it("read()", async function() { + const f = ["read"]; + await expectNonZeroRamCost(f); + }); + + it("peek()", async function() { + const f = ["peek"]; + await expectNonZeroRamCost(f); + }); + + it("clear()", async function() { + const f = ["clear"]; + await expectNonZeroRamCost(f); + }); + + it("getPortHandle()", async function() { + const f = ["getPortHandle"]; + await expectNonZeroRamCost(f); + }); + + it("rm()", async function() { + const f = ["rm"]; + await expectNonZeroRamCost(f); + }); + + it("scriptRunning()", async function() { + const f = ["scriptRunning"]; + await expectNonZeroRamCost(f); + }); + + it("scriptKill()", async function() { + const f = ["scriptKill"]; + await expectNonZeroRamCost(f); + }); + + it("getScriptName()", async function() { + const f = ["getScriptName"]; + await expectZeroRamCost(f); + }); + + it("getScriptRam()", async function() { + const f = ["getScriptRam"]; + await expectNonZeroRamCost(f); + }); + + it("getHackTime()", async function() { + const f = ["getHackTime"]; + await expectNonZeroRamCost(f); + }); + + it("getGrowTime()", async function() { + const f = ["getGrowTime"]; + await expectNonZeroRamCost(f); + }); + + it("getWeakenTime()", async function() { + const f = ["getWeakenTime"]; + await expectNonZeroRamCost(f); + }); + + it("getScriptIncome()", async function() { + const f = ["getScriptIncome"]; + await expectNonZeroRamCost(f); + }); + + it("getScriptExpGain()", async function() { + const f = ["getScriptExpGain"]; + await expectNonZeroRamCost(f); + }); + + it("getTimeSinceLastAug()", async function() { + const f = ["getTimeSinceLastAug"]; + await expectNonZeroRamCost(f); + }); + + it("sprintf()", async function() { + const f = ["sprintf"]; + await expectZeroRamCost(f); + }); + + it("vsprintf()", async function() { + const f = ["vsprintf"]; + await expectZeroRamCost(f); + }); + + it("nFormat()", async function() { + const f = ["nFormat"]; + await expectZeroRamCost(f); + }); + + it("prompt()", async function() { + const f = ["prompt"]; + await expectZeroRamCost(f); + }); + + it("wget()", async function() { + const f = ["wget"]; + await expectZeroRamCost(f); + }); + + it("getFavorToDonate()", async function() { + const f = ["getFavorToDonate"]; + await expectNonZeroRamCost(f); + }); + }); + + describe("Advanced Functions", async function() { + it("getBitNodeMultipliers()", async function() { + const f = ["getBitNodeMultipliers"]; + await expectNonZeroRamCost(f); + }); + }); + + describe("Hacknet Node API", async function() { + // The Hacknet Node API RAM cost is a bit different because + // it's just a one-time cost to access the 'hacknet' namespace. + // Otherwise, all functions cost 0 RAM + const apiFunctions = [ + "numNodes", + "purchaseNode", + "getPurchaseNodeCost", + "getNodeStats", + "upgradeLevel", + "upgradeRam", + "upgradeCore", + "upgradeCache", + "getLevelUpgradeCost", + "getRamUpgradeCost", + "getCoreUpgradeCost", + "getCacheUpgradeCost", + "numHashes", + "hashCost", + "spendHashes", + ] + it("should have zero RAM cost for all functions", function() { + for (const fn of apiFunctions) { + expect(getRamCost("hacknet", fn)).to.equal(0); + } + }); + + it("should incur a one time cost of for accesing the namespace", async function() { + let code = ""; + for (const fn of apiFunctions) { + code += ("hacknet." + fn + "(); "); + } + + const calculated = await calculateRamUsage(code, []); + testEquality(calculated, ScriptBaseCost + HacknetNamespaceCost); + }); + }); + + describe("TIX API", async function() { + it("getStockSymbols()", async function() { + const f = ["getStockSymbols"]; + await expectNonZeroRamCost(f); + }); + + it("getStockPrice()", async function() { + const f = ["getStockPrice"]; + await expectNonZeroRamCost(f); + }); + + it("getStockAskPrice()", async function() { + const f = ["getStockAskPrice"]; + await expectNonZeroRamCost(f); + }); + + it("getStockBidPrice()", async function() { + const f = ["getStockBidPrice"]; + await expectNonZeroRamCost(f); + }); + + it("getStockPosition()", async function() { + const f = ["getStockPosition"]; + await expectNonZeroRamCost(f); + }); + + it("getStockMaxShares()", async function() { + const f = ["getStockMaxShares"]; + await expectNonZeroRamCost(f); + }); + + it("getStockPurchaseCost()", async function() { + const f = ["getStockPurchaseCost"]; + await expectNonZeroRamCost(f); + }); + + it("getStockSaleGain()", async function() { + const f = ["getStockSaleGain"]; + await expectNonZeroRamCost(f); + }); + + it("buyStock()", async function() { + const f = ["buyStock"]; + await expectNonZeroRamCost(f); + }); + + it("sellStock()", async function() { + const f = ["sellStock"]; + await expectNonZeroRamCost(f); + }); + + it("shortStock()", async function() { + const f = ["shortStock"]; + await expectNonZeroRamCost(f); + }); + + it("sellShort()", async function() { + const f = ["sellShort"]; + await expectNonZeroRamCost(f); + }); + + it("placeOrder()", async function() { + const f = ["placeOrder"]; + await expectNonZeroRamCost(f); + }); + + it("cancelOrder()", async function() { + const f = ["cancelOrder"]; + await expectNonZeroRamCost(f); + }); + + it("getOrders()", async function() { + const f = ["getOrders"]; + await expectNonZeroRamCost(f); + }); + + it("getStockVolatility()", async function() { + const f = ["getStockVolatility"]; + await expectNonZeroRamCost(f); + }); + + it("getStockForecast()", async function() { + const f = ["getStockForecast"]; + await expectNonZeroRamCost(f); + }); + + it("purchase4SMarketData()", async function() { + const f = ["purchase4SMarketData"]; + await expectNonZeroRamCost(f); + }); + + it("purchase4SMarketDataTixApi()", async function() { + const f = ["purchase4SMarketDataTixApi"]; + await expectNonZeroRamCost(f); + }); + }); + + describe("Singularity Functions", async function() { + it("universityCourse()", async function() { + const f = ["universityCourse"]; + await expectNonZeroRamCost(f); + }); + + it("gymWorkout()", async function() { + const f = ["gymWorkout"]; + await expectNonZeroRamCost(f); + }); + + it("travelToCity()", async function() { + const f = ["travelToCity"]; + await expectNonZeroRamCost(f); + }); + + it("purchaseTor()", async function() { + const f = ["purchaseTor"]; + await expectNonZeroRamCost(f); + }); + + it("purchaseProgram()", async function() { + const f = ["purchaseProgram"]; + await expectNonZeroRamCost(f); + }); + + it("getStats()", async function() { + const f = ["getStats"]; + await expectNonZeroRamCost(f); + }); + + it("getCharacterInformation()", async function() { + const f = ["getCharacterInformation"]; + await expectNonZeroRamCost(f); + }); + + it("isBusy()", async function() { + const f = ["isBusy"]; + await expectNonZeroRamCost(f); + }); + + it("stopAction()", async function() { + const f = ["stopAction"]; + await expectNonZeroRamCost(f); + }); + + it("upgradeHomeRam()", async function() { + const f = ["upgradeHomeRam"]; + await expectNonZeroRamCost(f); + }); + + it("getUpgradeHomeRamCost()", async function() { + const f = ["getUpgradeHomeRamCost"]; + await expectNonZeroRamCost(f); + }); + + it("workForCompany()", async function() { + const f = ["workForCompany"]; + await expectNonZeroRamCost(f); + }); + + it("applyToCompany()", async function() { + const f = ["applyToCompany"]; + await expectNonZeroRamCost(f); + }); + + it("getCompanyRep()", async function() { + const f = ["getCompanyRep"]; + await expectNonZeroRamCost(f); + }); + + it("getCompanyFavor()", async function() { + const f = ["getCompanyFavor"]; + await expectNonZeroRamCost(f); + }); + + it("getCompanyFavorGain()", async function() { + const f = ["getCompanyFavorGain"]; + await expectNonZeroRamCost(f); + }); + + it("checkFactionInvitations()", async function() { + const f = ["checkFactionInvitations"]; + await expectNonZeroRamCost(f); + }); + + it("joinFaction()", async function() { + const f = ["joinFaction"]; + await expectNonZeroRamCost(f); + }); + + it("workForFaction()", async function() { + const f = ["workForFaction"]; + await expectNonZeroRamCost(f); + }); + + it("getFactionRep()", async function() { + const f = ["getFactionRep"]; + await expectNonZeroRamCost(f); + }); + + it("getFactionFavor()", async function() { + const f = ["getFactionFavor"]; + await expectNonZeroRamCost(f); + }); + + it("getFactionFavorGain()", async function() { + const f = ["getFactionFavorGain"]; + await expectNonZeroRamCost(f); + }); + + it("donateToFaction()", async function() { + const f = ["donateToFaction"]; + await expectNonZeroRamCost(f); + }); + + it("createProgram()", async function() { + const f = ["createProgram"]; + await expectNonZeroRamCost(f); + }); + + it("commitCrime()", async function() { + const f = ["commitCrime"]; + await expectNonZeroRamCost(f); + }); + + it("getCrimeChance()", async function() { + const f = ["getCrimeChance"]; + await expectNonZeroRamCost(f); + }); + + it("getOwnedAugmentations()", async function() { + const f = ["getOwnedAugmentations"]; + await expectNonZeroRamCost(f); + }); + + it("getOwnedSourceFiles()", async function() { + const f = ["getOwnedSourceFiles"]; + await expectNonZeroRamCost(f); + }); + + it("getAugmentationsFromFaction()", async function() { + const f = ["getAugmentationsFromFaction"]; + await expectNonZeroRamCost(f); + }); + + it("getAugmentationPrereq()", async function() { + const f = ["getAugmentationPrereq"]; + await expectNonZeroRamCost(f); + }); + + it("getAugmentationCost()", async function() { + const f = ["getAugmentationCost"]; + await expectNonZeroRamCost(f); + }); + + it("purchaseAugmentation()", async function() { + const f = ["purchaseAugmentation"]; + await expectNonZeroRamCost(f); + }); + + it("installAugmentations()", async function() { + const f = ["installAugmentations"]; + await expectNonZeroRamCost(f); + }); + }); + + describe("Bladeburner API", async function() { + it("getContractNames()", async function() { + const f = ["bladeburner", "getContractNames"]; + await expectNonZeroRamCost(f); + }); + + it("getOperationNames()", async function() { + const f = ["bladeburner", "getOperationNames"]; + await expectNonZeroRamCost(f); + }); + + it("getBlackOpNames()", async function() { + const f = ["bladeburner", "getBlackOpNames"]; + await expectNonZeroRamCost(f); + }); + + it("getGeneralActionNames()", async function() { + const f = ["bladeburner", "getGeneralActionNames"]; + await expectNonZeroRamCost(f); + }); + + it("getSkillNames()", async function() { + const f = ["bladeburner", "getSkillNames"]; + await expectNonZeroRamCost(f); + }); + + it("startAction()", async function() { + const f = ["bladeburner", "startAction"]; + await expectNonZeroRamCost(f); + }); + + it("stopBladeburnerAction()", async function() { + const f = ["bladeburner", "stopBladeburnerAction"]; + await expectNonZeroRamCost(f); + }); + + it("getCurrentAction()", async function() { + const f = ["bladeburner", "getCurrentAction"]; + await expectNonZeroRamCost(f); + }); + + it("getActionTime()", async function() { + const f = ["bladeburner", "getActionTime"]; + await expectNonZeroRamCost(f); + }); + + it("getActionEstimatedSuccessChance()", async function() { + const f = ["bladeburner", "getActionEstimatedSuccessChance"]; + await expectNonZeroRamCost(f); + }); + + it("getActionRepGain()", async function() { + const f = ["bladeburner", "getActionRepGain"]; + await expectNonZeroRamCost(f); + }); + + it("getActionCountRemaining()", async function() { + const f = ["bladeburner", "getActionCountRemaining"]; + await expectNonZeroRamCost(f); + }); + + it("getActionMaxLevel()", async function() { + const f = ["bladeburner", "getActionMaxLevel"]; + await expectNonZeroRamCost(f); + }); + + it("getActionCurrentLevel()", async function() { + const f = ["bladeburner", "getActionCurrentLevel"]; + await expectNonZeroRamCost(f); + }); + + it("getActionAutolevel()", async function() { + const f = ["bladeburner", "getActionAutolevel"]; + await expectNonZeroRamCost(f); + }); + + it("setActionAutolevel()", async function() { + const f = ["bladeburner", "setActionAutolevel"]; + await expectNonZeroRamCost(f); + }); + + it("setActionLevel()", async function() { + const f = ["bladeburner", "setActionLevel"]; + await expectNonZeroRamCost(f); + }); + + it("getRank()", async function() { + const f = ["bladeburner", "getRank"]; + await expectNonZeroRamCost(f); + }); + + it("getBlackOpRank()", async function() { + const f = ["bladeburner", "getBlackOpRank"]; + await expectNonZeroRamCost(f); + }); + + it("getSkillPoints()", async function() { + const f = ["bladeburner", "getSkillPoints"]; + await expectNonZeroRamCost(f); + }); + + it("getSkillLevel()", async function() { + const f = ["bladeburner", "getSkillLevel"]; + await expectNonZeroRamCost(f); + }); + + it("getSkillUpgradeCost()", async function() { + const f = ["bladeburner", "getSkillUpgradeCost"]; + await expectNonZeroRamCost(f); + }); + + it("upgradeSkill()", async function() { + const f = ["bladeburner", "upgradeSkill"]; + await expectNonZeroRamCost(f); + }); + + it("getTeamSize()", async function() { + const f = ["bladeburner", "getTeamSize"]; + await expectNonZeroRamCost(f); + }); + + it("setTeamSize()", async function() { + const f = ["bladeburner", "setTeamSize"]; + await expectNonZeroRamCost(f); + }); + + it("getCityEstimatedPopulation()", async function() { + const f = ["bladeburner", "getCityEstimatedPopulation"]; + await expectNonZeroRamCost(f); + }); + + it("getCityEstimatedCommunities()", async function() { + const f = ["bladeburner", "getCityEstimatedCommunities"]; + await expectNonZeroRamCost(f); + }); + + it("getCityChaos()", async function() { + const f = ["bladeburner", "getCityChaos"]; + await expectNonZeroRamCost(f); + }); + + it("getCity()", async function() { + const f = ["bladeburner", "getCity"]; + await expectNonZeroRamCost(f); + }); + + it("switchCity()", async function() { + const f = ["bladeburner", "switchCity"]; + await expectNonZeroRamCost(f); + }); + + it("getStamina()", async function() { + const f = ["bladeburner", "getStamina"]; + await expectNonZeroRamCost(f); + }); + + it("joinBladeburnerFaction()", async function() { + const f = ["bladeburner", "joinBladeburnerFaction"]; + await expectNonZeroRamCost(f); + }); + + it("joinBladeburnerDivision()", async function() { + const f = ["bladeburner", "joinBladeburnerDivision"]; + await expectNonZeroRamCost(f); + }); + + it("getBonusTime()", async function() { + const f = ["bladeburner", "getBonusTime"]; + await expectZeroRamCost(f); + }); + }); + + describe("Gang API", async function() { + it("getMemberNames()", async function() { + const f = ["gang", "getMemberNames"]; + await expectNonZeroRamCost(f); + }); + + it("getGangInformation()", async function() { + const f = ["gang", "getGangInformation"]; + await expectNonZeroRamCost(f); + }); + + it("getOtherGangInformation()", async function() { + const f = ["gang", "getOtherGangInformation"]; + await expectNonZeroRamCost(f); + }); + + it("getMemberInformation()", async function() { + const f = ["gang", "getMemberInformation"]; + await expectNonZeroRamCost(f); + }); + + it("canRecruitMember()", async function() { + const f = ["gang", "canRecruitMember"]; + await expectNonZeroRamCost(f); + }); + + it("recruitMember()", async function() { + const f = ["gang", "recruitMember"]; + await expectNonZeroRamCost(f); + }); + + it("getTaskNames()", async function() { + const f = ["gang", "getTaskNames"]; + await expectNonZeroRamCost(f); + }); + + it("setMemberTask()", async function() { + const f = ["gang", "setMemberTask"]; + await expectNonZeroRamCost(f); + }); + + it("getEquipmentNames()", async function() { + const f = ["gang", "getEquipmentNames"]; + await expectNonZeroRamCost(f); + }); + + it("getEquipmentCost()", async function() { + const f = ["gang", "getEquipmentCost"]; + await expectNonZeroRamCost(f); + }); + + it("getEquipmentType()", async function() { + const f = ["gang", "getEquipmentType"]; + await expectNonZeroRamCost(f); + }); + + it("purchaseEquipment()", async function() { + const f = ["gang", "purchaseEquipment"]; + await expectNonZeroRamCost(f); + }); + + it("ascendMember()", async function() { + const f = ["gang", "ascendMember"]; + await expectNonZeroRamCost(f); + }); + + it("setTerritoryWarfare()", async function() { + const f = ["gang", "setTerritoryWarfare"]; + await expectNonZeroRamCost(f); + }); + + it("getChanceToWinClash()", async function() { + const f = ["gang", "getChanceToWinClash"]; + await expectNonZeroRamCost(f); + }); + + it("getBonusTime()", async function() { + const f = ["gang", "getBonusTime"]; + await expectZeroRamCost(f); + }); + }); + + describe("Coding Contract API", async function() { + it("attempt()", async function() { + const f = ["codingcontract", "attempt"]; + await expectNonZeroRamCost(f); + }); + + it("getContractType()", async function() { + const f = ["codingcontract", "getContractType"]; + await expectNonZeroRamCost(f); + }); + + it("getDescription()", async function() { + const f = ["codingcontract", "getDescription"]; + await expectNonZeroRamCost(f); + }); + + it("getData()", async function() { + const f = ["codingcontract", "getData"]; + await expectNonZeroRamCost(f); + }); + + it("getNumTriesRemaining()", async function() { + const f = ["codingcontract", "getNumTriesRemaining"]; + await expectNonZeroRamCost(f); + }); + }); + + describe("Sleeve API", async function() { + it("getNumSleeves()", async function() { + const f = ["sleeve", "getNumSleeves"]; + await expectNonZeroRamCost(f); + }); + + it("getSleeveStats()", async function() { + const f = ["sleeve", "getSleeveStats"]; + await expectNonZeroRamCost(f); + }); + + it("getInformation()", async function() { + const f = ["sleeve", "getInformation"]; + await expectNonZeroRamCost(f); + }); + + it("getTask()", async function() { + const f = ["sleeve", "getTask"]; + await expectNonZeroRamCost(f); + }); + + it("setToShockRecovery()", async function() { + const f = ["sleeve", "setToShockRecovery"]; + await expectNonZeroRamCost(f); + }); + + it("setToSynchronize()", async function() { + const f = ["sleeve", "setToSynchronize"]; + await expectNonZeroRamCost(f); + }); + + it("setToCommitCrime()", async function() { + const f = ["sleeve", "setToCommitCrime"]; + await expectNonZeroRamCost(f); + }); + + it("setToFactionWork()", async function() { + const f = ["sleeve", "setToFactionWork"]; + await expectNonZeroRamCost(f); + }); + + it("setToCompanyWork()", async function() { + const f = ["sleeve", "setToCompanyWork"]; + await expectNonZeroRamCost(f); + }); + + it("setToUniversityCourse()", async function() { + const f = ["sleeve", "setToUniversityCourse"]; + await expectNonZeroRamCost(f); + }); + + it("setToGymWorkout()", async function() { + const f = ["sleeve", "setToGymWorkout"]; + await expectNonZeroRamCost(f); + }); + + it("travel()", async function() { + const f = ["sleeve", "travel"]; + await expectNonZeroRamCost(f); + }); + + it("getSleeveAugmentations()", async function() { + const f = ["sleeve", "getSleeveAugmentations"]; + await expectNonZeroRamCost(f); + }); + + it("getSleevePurchasableAugs()", async function() { + const f = ["sleeve", "getSleevePurchasableAugs"]; + await expectNonZeroRamCost(f); + }); + + it("purchaseSleeveAug()", async function() { + const f = ["sleeve", "purchaseSleeveAug"]; + await expectNonZeroRamCost(f); + }); + }); }); diff --git a/test/README.md b/test/README.md index dc57f24cc..cf0484dd7 100644 --- a/test/README.md +++ b/test/README.md @@ -1,5 +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. +Unit tests use Mocha/Chai and are run using mochapack (mocha-webpack fork). +Run the test command with `npm run test` diff --git a/test/StockMarketTests.js b/test/StockMarketTests.js index 53283940f..c177dfbb6 100644 --- a/test/StockMarketTests.js +++ b/test/StockMarketTests.js @@ -1,8 +1,7 @@ import { CONSTANTS } from "../src/Constants"; import { Order } from "../src/StockMarket/Order"; -//import { processOrders } from "../src/StockMarket/OrderProcessing"; +// import { processOrders } from "../src/StockMarket/OrderProcessing"; import { Stock } from "../src/StockMarket/Stock"; -/* import { deleteStockMarket, initStockMarket, @@ -11,7 +10,6 @@ import { StockMarket, SymbolToStockMap, } from "../src/StockMarket/StockMarket"; -*/ import { calculateIncreasingPriceMovement, calculateDecreasingPriceMovement, @@ -24,8 +22,9 @@ import { import { OrderTypes } from "../src/StockMarket/data/OrderTypes" import { PositionTypes } from "../src/StockMarket/data/PositionTypes"; -const assert = chai.assert; -const expect = chai.expect; +//const assert = chai.assert; +//const expect = chai.expect; +import { expect } from "chai"; console.log("Beginning Stock Market Tests"); diff --git a/test/index.html b/test/index.html index 8767e8875..da13a15cb 100644 --- a/test/index.html +++ b/test/index.html @@ -1,5 +1,5 @@ - + Mocha Tests diff --git a/test/index.js b/test/index.js index 4f65f6efd..344ddca0f 100644 --- a/test/index.js +++ b/test/index.js @@ -1,2 +1,3 @@ +// export * from "./Netscript/DynamicRamCalculationTests"; export * from "./Netscript/StaticRamCalculationTests"; export * from "./StockMarketTests"; diff --git a/test/tests.bundle.js b/test/tests.bundle.js deleted file mode 100644 index 1e0f415e6..000000000 --- a/test/tests.bundle.js +++ /dev/null @@ -1,2035 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // 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 = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 300); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ 10: -/*!*******************************************!*\ - !*** ./src/Netscript/RamCostGenerator.ts ***! - \*******************************************/ -/*! no static exports found */ -/*! all exports used */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -// TODO remember to update RamCalculations.js and WorkerScript.js -// RAM costs for Netscript functions -exports.RamCostConstants = { - ScriptBaseRamCost: 1.6, - ScriptDomRamCost: 25, - ScriptHackRamCost: 0.1, - ScriptHackAnalyzeRamCost: 1, - ScriptGrowRamCost: 0.15, - ScriptGrowthAnalyzeRamCost: 1, - ScriptWeakenRamCost: 0.15, - ScriptScanRamCost: 0.2, - ScriptPortProgramRamCost: 0.05, - ScriptRunRamCost: 1.0, - ScriptExecRamCost: 1.3, - ScriptSpawnRamCost: 2.0, - ScriptScpRamCost: 0.6, - ScriptKillRamCost: 0.5, - ScriptHasRootAccessRamCost: 0.05, - ScriptGetHostnameRamCost: 0.05, - ScriptGetHackingLevelRamCost: 0.05, - ScriptGetMultipliersRamCost: 4.0, - ScriptGetServerRamCost: 0.1, - ScriptFileExistsRamCost: 0.1, - ScriptIsRunningRamCost: 0.1, - ScriptHacknetNodesRamCost: 4.0, - ScriptHNUpgLevelRamCost: 0.4, - ScriptHNUpgRamRamCost: 0.6, - ScriptHNUpgCoreRamCost: 0.8, - ScriptGetStockRamCost: 2.0, - ScriptBuySellStockRamCost: 2.5, - ScriptGetPurchaseServerRamCost: 0.25, - ScriptPurchaseServerRamCost: 2.25, - ScriptGetPurchasedServerLimit: 0.05, - ScriptGetPurchasedServerMaxRam: 0.05, - ScriptRoundRamCost: 0.05, - ScriptReadWriteRamCost: 1.0, - ScriptArbScriptRamCost: 1.0, - ScriptGetScriptRamCost: 0.1, - ScriptGetHackTimeRamCost: 0.05, - ScriptGetFavorToDonate: 0.10, - ScriptCodingContractBaseRamCost: 10, - ScriptSleeveBaseRamCost: 4, - ScriptSingularityFn1RamCost: 2, - ScriptSingularityFn2RamCost: 3, - ScriptSingularityFn3RamCost: 5, - ScriptGangApiBaseRamCost: 4, - ScriptBladeburnerApiBaseRamCost: 4, -}; -exports.RamCosts = { - hacknet: { - numNodes: () => 0, - purchaseNode: () => 0, - getPurchaseNodeCost: () => 0, - getNodeStats: () => 0, - upgradeLevel: () => 0, - upgradeRam: () => 0, - upgradeCore: () => 0, - upgradeCache: () => 0, - getLevelUpgradeCost: () => 0, - getRamUpgradeCost: () => 0, - getCoreUpgradeCost: () => 0, - getCacheUpgradeCost: () => 0, - numHashes: () => 0, - hashCost: () => 0, - spendHashes: () => 0, - }, - sprintf: () => 0, - vsprintf: () => 0, - scan: () => exports.RamCostConstants.ScriptScanRamCost, - hack: () => exports.RamCostConstants.ScriptHackRamCost, - hackAnalyzeThreads: () => exports.RamCostConstants.ScriptHackAnalyzeRamCost, - hackAnalyzePercent: () => exports.RamCostConstants.ScriptHackAnalyzeRamCost, - hackChance: () => exports.RamCostConstants.ScriptHackAnalyzeRamCost, - sleep: () => 0, - grow: () => exports.RamCostConstants.ScriptGrowRamCost, - growthAnalyze: () => exports.RamCostConstants.ScriptGrowthAnalyzeRamCost, - weaken: () => exports.RamCostConstants.ScriptWeakenRamCost, - print: () => 0, - tprint: () => 0, - clearLog: () => 0, - disableLog: () => 0, - enableLog: () => 0, - isLogEnabled: () => 0, - getScriptLogs: () => 0, - nuke: () => exports.RamCostConstants.ScriptPortProgramRamCost, - brutessh: () => exports.RamCostConstants.ScriptPortProgramRamCost, - ftpcrack: () => exports.RamCostConstants.ScriptPortProgramRamCost, - relaysmtp: () => exports.RamCostConstants.ScriptPortProgramRamCost, - httpworm: () => exports.RamCostConstants.ScriptPortProgramRamCost, - sqlinject: () => exports.RamCostConstants.ScriptPortProgramRamCost, - run: () => exports.RamCostConstants.ScriptRunRamCost, - exec: () => exports.RamCostConstants.ScriptExecRamCost, - spawn: () => exports.RamCostConstants.ScriptSpawnRamCost, - kill: () => exports.RamCostConstants.ScriptKillRamCost, - killall: () => exports.RamCostConstants.ScriptKillRamCost, - exit: () => 0, - scp: () => exports.RamCostConstants.ScriptScpRamCost, - ls: () => exports.RamCostConstants.ScriptScanRamCost, - ps: () => exports.RamCostConstants.ScriptScanRamCost, - hasRootAccess: () => exports.RamCostConstants.ScriptHasRootAccessRamCost, - getIp: () => exports.RamCostConstants.ScriptGetHostnameRamCost, - getHostname: () => exports.RamCostConstants.ScriptGetHostnameRamCost, - getHackingLevel: () => exports.RamCostConstants.ScriptGetHackingLevelRamCost, - getHackingMultipliers: () => exports.RamCostConstants.ScriptGetMultipliersRamCost, - getHacknetMultipliers: () => exports.RamCostConstants.ScriptGetMultipliersRamCost, - getBitNodeMultipliers: () => exports.RamCostConstants.ScriptGetMultipliersRamCost, - getServerMoneyAvailable: () => exports.RamCostConstants.ScriptGetServerRamCost, - getServerSecurityLevel: () => exports.RamCostConstants.ScriptGetServerRamCost, - getServerBaseSecurityLevel: () => exports.RamCostConstants.ScriptGetServerRamCost, - getServerMinSecurityLevel: () => exports.RamCostConstants.ScriptGetServerRamCost, - getServerRequiredHackingLevel: () => exports.RamCostConstants.ScriptGetServerRamCost, - getServerMaxMoney: () => exports.RamCostConstants.ScriptGetServerRamCost, - getServerGrowth: () => exports.RamCostConstants.ScriptGetServerRamCost, - getServerNumPortsRequired: () => exports.RamCostConstants.ScriptGetServerRamCost, - getServerRam: () => exports.RamCostConstants.ScriptGetServerRamCost, - serverExists: () => exports.RamCostConstants.ScriptGetServerRamCost, - fileExists: () => exports.RamCostConstants.ScriptFileExistsRamCost, - isRunning: () => exports.RamCostConstants.ScriptIsRunningRamCost, - getStockSymbols: () => exports.RamCostConstants.ScriptGetStockRamCost, - getStockPrice: () => exports.RamCostConstants.ScriptGetStockRamCost, - getStockAskPrice: () => exports.RamCostConstants.ScriptGetStockRamCost, - getStockBidPrice: () => exports.RamCostConstants.ScriptGetStockRamCost, - getStockPosition: () => exports.RamCostConstants.ScriptGetStockRamCost, - getStockMaxShares: () => exports.RamCostConstants.ScriptGetStockRamCost, - getStockPurchaseCost: () => exports.RamCostConstants.ScriptGetStockRamCost, - getStockSaleGain: () => exports.RamCostConstants.ScriptGetStockRamCost, - buyStock: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - sellStock: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - shortStock: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - sellShort: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - placeOrder: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - cancelOrder: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - getOrders: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - getStockVolatility: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - getStockForecast: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - purchase4SMarketData: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - purchase4SMarketDataTixApi: () => exports.RamCostConstants.ScriptBuySellStockRamCost, - getPurchasedServerLimit: () => exports.RamCostConstants.ScriptGetPurchasedServerLimit, - getPurchasedServerMaxRam: () => exports.RamCostConstants.ScriptGetPurchasedServerMaxRam, - getPurchasedServerCost: () => exports.RamCostConstants.ScriptGetPurchaseServerRamCost, - purchaseServer: () => exports.RamCostConstants.ScriptPurchaseServerRamCost, - deleteServer: () => exports.RamCostConstants.ScriptPurchaseServerRamCost, - getPurchasedServers: () => exports.RamCostConstants.ScriptPurchaseServerRamCost, - write: () => exports.RamCostConstants.ScriptReadWriteRamCost, - tryWrite: () => exports.RamCostConstants.ScriptReadWriteRamCost, - read: () => exports.RamCostConstants.ScriptReadWriteRamCost, - peek: () => exports.RamCostConstants.ScriptReadWriteRamCost, - clear: () => exports.RamCostConstants.ScriptReadWriteRamCost, - getPortHandle: () => exports.RamCostConstants.ScriptReadWriteRamCost * 10, - rm: () => exports.RamCostConstants.ScriptReadWriteRamCost, - scriptRunning: () => exports.RamCostConstants.ScriptArbScriptRamCost, - scriptKill: () => exports.RamCostConstants.ScriptArbScriptRamCost, - getScriptName: () => 0, - getScriptRam: () => exports.RamCostConstants.ScriptGetScriptRamCost, - getHackTime: () => exports.RamCostConstants.ScriptGetHackTimeRamCost, - getGrowTime: () => exports.RamCostConstants.ScriptGetHackTimeRamCost, - getWeakenTime: () => exports.RamCostConstants.ScriptGetHackTimeRamCost, - getScriptIncome: () => exports.RamCostConstants.ScriptGetScriptRamCost, - getScriptExpGain: () => exports.RamCostConstants.ScriptGetScriptRamCost, - nFormat: () => 0, - getTimeSinceLastAug: () => exports.RamCostConstants.ScriptGetHackTimeRamCost, - prompt: () => 0, - wget: () => 0, - getFavorToDonate: () => exports.RamCostConstants.ScriptGetFavorToDonate, - // Singularity Functions - universityCourse: () => exports.RamCostConstants.ScriptSingularityFn1RamCost, - gymWorkout: () => exports.RamCostConstants.ScriptSingularityFn1RamCost, - travelToCity: () => exports.RamCostConstants.ScriptSingularityFn1RamCost, - purchaseTor: () => exports.RamCostConstants.ScriptSingularityFn1RamCost, - purchaseProgram: () => exports.RamCostConstants.ScriptSingularityFn1RamCost, - getStats: () => exports.RamCostConstants.ScriptSingularityFn1RamCost / 4, - getCharacterInformation: () => exports.RamCostConstants.ScriptSingularityFn1RamCost / 4, - isBusy: () => exports.RamCostConstants.ScriptSingularityFn1RamCost / 4, - stopAction: () => exports.RamCostConstants.ScriptSingularityFn1RamCost / 2, - upgradeHomeRam: () => exports.RamCostConstants.ScriptSingularityFn2RamCost, - getUpgradeHomeRamCost: () => exports.RamCostConstants.ScriptSingularityFn2RamCost / 2, - workForCompany: () => exports.RamCostConstants.ScriptSingularityFn2RamCost, - applyToCompany: () => exports.RamCostConstants.ScriptSingularityFn2RamCost, - getCompanyRep: () => exports.RamCostConstants.ScriptSingularityFn2RamCost / 3, - getCompanyFavor: () => exports.RamCostConstants.ScriptSingularityFn2RamCost / 3, - getCompanyFavorGain: () => exports.RamCostConstants.ScriptSingularityFn2RamCost / 4, - checkFactionInvitations: () => exports.RamCostConstants.ScriptSingularityFn2RamCost, - joinFaction: () => exports.RamCostConstants.ScriptSingularityFn2RamCost, - workForFaction: () => exports.RamCostConstants.ScriptSingularityFn2RamCost, - getFactionRep: () => exports.RamCostConstants.ScriptSingularityFn2RamCost / 3, - getFactionFavor: () => exports.RamCostConstants.ScriptSingularityFn2RamCost / 3, - getFactionFavorGain: () => exports.RamCostConstants.ScriptSingularityFn2RamCost / 4, - donateToFaction: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - createProgram: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - commitCrime: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - getCrimeChance: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - getOwnedAugmentations: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - getOwnedSourceFiles: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - getAugmentationsFromFaction: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - getAugmentationPrereq: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - getAugmentationCost: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - purchaseAugmentation: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - installAugmentations: () => exports.RamCostConstants.ScriptSingularityFn3RamCost, - // Gang API - gang: { - getMemberNames: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 4, - getGangInformation: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 2, - getOtherGangInformation: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 2, - getMemberInformation: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 2, - canRecruitMember: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 4, - recruitMember: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 2, - getTaskNames: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 4, - setMemberTask: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 2, - getEquipmentNames: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 4, - getEquipmentCost: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 2, - getEquipmentType: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 2, - purchaseEquipment: () => exports.RamCostConstants.ScriptGangApiBaseRamCost, - ascendMember: () => exports.RamCostConstants.ScriptGangApiBaseRamCost, - setTerritoryWarfare: () => exports.RamCostConstants.ScriptGangApiBaseRamCost / 2, - getChanceToWinClash: () => exports.RamCostConstants.ScriptGangApiBaseRamCost, - getBonusTime: () => 0, - }, - // Bladeburner API - bladeburner: { - getContractNames: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10, - getOperationNames: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10, - getBlackOpNames: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10, - getBlackOpRank: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost / 2, - getGeneralActionNames: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10, - getSkillNames: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10, - startAction: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - stopBladeburnerAction: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost / 2, - getCurrentAction: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost / 4, - getActionTime: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getActionEstimatedSuccessChance: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getActionRepGain: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getActionCountRemaining: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getActionMaxLevel: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getActionCurrentLevel: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getActionAutolevel: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - setActionAutolevel: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - setActionLevel: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getRank: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getSkillPoints: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getSkillLevel: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getSkillUpgradeCost: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - upgradeSkill: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getTeamSize: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - setTeamSize: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getCityEstimatedPopulation: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getCityEstimatedCommunities: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getCityChaos: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getCity: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - switchCity: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getStamina: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - joinBladeburnerFaction: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - joinBladeburnerDivision: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - getBonusTime: () => exports.RamCostConstants.ScriptBladeburnerApiBaseRamCost, - }, - // Coding Contract API - codingcontract: { - attempt: () => exports.RamCostConstants.ScriptCodingContractBaseRamCost, - getContractType: () => exports.RamCostConstants.ScriptCodingContractBaseRamCost / 2, - getData: () => exports.RamCostConstants.ScriptCodingContractBaseRamCost / 2, - getDescription: () => exports.RamCostConstants.ScriptCodingContractBaseRamCost / 2, - getNumTriesRemaining: () => exports.RamCostConstants.ScriptCodingContractBaseRamCost / 2, - }, - // Duplicate Sleeve API - sleeve: { - getNumSleeves: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - setToShockRecovery: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - setToSynchronize: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - setToCommitCrime: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - setToUniversityCourse: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - travel: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - setToCompanyWork: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - setToFactionWork: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - setToGymWorkout: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - getSleeveStats: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - getTask: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - getInformation: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - getSleeveAugmentations: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - getSleevePurchasableAugs: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - purchaseSleeveAug: () => exports.RamCostConstants.ScriptSleeveBaseRamCost, - }, - heart: { - // Easter egg function - break: () => 0, - } -}; -function getRamCost(...args) { - if (args.length === 0) { - console.warn(`No arguments passed to getRamCost()`); - return 0; - } - let curr = exports.RamCosts[args[0]]; - for (let i = 1; i < args.length; ++i) { - if (curr == null) { - console.warn(`Invalid function passed to getRamCost: ${args}`); - return 0; - } - const currType = typeof curr; - if (currType === "function" || currType === "number") { - break; - } - curr = curr[args[i]]; - } - const currType = typeof curr; - if (currType === "function") { - return curr(); - } - if (currType === "number") { - return curr; - } - console.warn(`Expected type: ${currType}`); - return 0; -} -exports.getRamCost = getRamCost; - - -/***/ }), - -/***/ 15: -/*!***************************************!*\ - !*** ./utils/helpers/getRandomInt.ts ***! - \***************************************/ -/*! no static exports found */ -/*! all exports used */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Gets a random integer bounded by the values passed in. - * @param min The minimum value in the range. - * @param max The maximum value in the range. - */ -function getRandomInt(min, max) { - const lower = Math.min(min, max); - const upper = Math.max(min, max); - return Math.floor(Math.random() * (upper - lower + 1)) + lower; -} -exports.getRandomInt = getRandomInt; - - -/***/ }), - -/***/ 16: -/*!******************************!*\ - !*** ./utils/JSONReviver.js ***! - \******************************/ -/*! exports provided: Reviver, Generic_toJSON, Generic_fromJSON */ -/*! all exports used */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Reviver", function() { return Reviver; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Generic_toJSON", function() { return Generic_toJSON; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Generic_fromJSON", function() { return Generic_fromJSON; }); -/* Generic Reviver, toJSON, and fromJSON functions used for saving and loading objects */ - -// A generic "smart reviver" function. -// Looks for object values with a `ctor` property and -// a `data` property. If it finds them, and finds a matching -// constructor that has a `fromJSON` property on it, it hands -// off to that `fromJSON` fuunction, passing in the value. -function Reviver(key, value) { - var ctor; - if (value == null) { - console.log("Reviver WRONGLY called with key: " + key + ", and value: " + value); - return 0; - } - - if (typeof value === "object" && - typeof value.ctor === "string" && - typeof value.data !== "undefined") { - // Compatibility for version v0.43.1 - // TODO Remove this eventually - if (value.ctor === "AllServersMap") { - console.log('Converting AllServersMap for v0.43.1'); - return value.data; - } - - ctor = Reviver.constructors[value.ctor] || window[value.ctor]; - - if (typeof ctor === "function" && - typeof ctor.fromJSON === "function") { - - return ctor.fromJSON(value); - } - } - return value; -} -Reviver.constructors = {}; // A list of constructors the smart reviver should know about - -// A generic "toJSON" function that creates the data expected -// by Reviver. -// `ctorName` The name of the constructor to use to revive it -// `obj` The object being serialized -// `keys` (Optional) Array of the properties to serialize, -// if not given then all of the objects "own" properties -// that don't have function values will be serialized. -// (Note: If you list a property in `keys`, it will be serialized -// regardless of whether it's an "own" property.) -// Returns: The structure (which will then be turned into a string -// as part of the JSON.stringify algorithm) -function Generic_toJSON(ctorName, obj, keys) { - var data, index, key; - - if (!keys) { - keys = Object.keys(obj); // Only "own" properties are included - } - - data = {}; - for (let index = 0; index < keys.length; ++index) { - key = keys[index]; - data[key] = obj[key]; - } - return {ctor: ctorName, data: data}; -} - -// A generic "fromJSON" function for use with Reviver: Just calls the -// constructor function with no arguments, then applies all of the -// key/value pairs from the raw data to the instance. Only useful for -// constructors that can be reasonably called without arguments! -// `ctor` The constructor to call -// `data` The data to apply -// Returns: The object -function Generic_fromJSON(ctor, data) { - var obj, name; - - obj = new ctor(); - for (name in data) { - obj[name] = data[name]; - } - return obj; -} - - - - -/***/ }), - -/***/ 205: -/*!**********************************!*\ - !*** ./test/StockMarketTests.js ***! - \**********************************/ -/*! no exports provided */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var _src_Constants__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../src/Constants */ 8); -/* harmony import */ var _src_Constants__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_src_Constants__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _src_StockMarket_Order__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../src/StockMarket/Order */ 98); -/* harmony import */ var _src_StockMarket_Order__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_src_StockMarket_Order__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var _src_StockMarket_Stock__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../src/StockMarket/Stock */ 66); -/* harmony import */ var _src_StockMarket_Stock__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_src_StockMarket_Stock__WEBPACK_IMPORTED_MODULE_2__); -/* harmony import */ var _src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../src/StockMarket/StockMarketHelpers */ 27); -/* harmony import */ var _src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__); -/* harmony import */ var _src_StockMarket_data_OrderTypes__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../src/StockMarket/data/OrderTypes */ 54); -/* harmony import */ var _src_StockMarket_data_OrderTypes__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_src_StockMarket_data_OrderTypes__WEBPACK_IMPORTED_MODULE_4__); -/* harmony import */ var _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../src/StockMarket/data/PositionTypes */ 23); -/* harmony import */ var _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__); - - -//import { processOrders } from "../src/StockMarket/OrderProcessing"; - -/* -import { - deleteStockMarket, - initStockMarket, - initSymbolToStockMap, - loadStockMarket, - StockMarket, - SymbolToStockMap, -} from "../src/StockMarket/StockMarket"; -*/ - - - - -const assert = chai.assert; -const expect = chai.expect; - -console.log("Beginning Stock Market Tests"); - -describe("Stock Market Tests", function() { - const commission = _src_Constants__WEBPACK_IMPORTED_MODULE_0__["CONSTANTS"].StockMarketCommission; - - // Generic Stock object that can be used by each test - let stock; - const ctorParams = { - b: true, - initPrice: 10e3, - marketCap: 5e9, - mv: 1, - name: "MockStock", - otlkMag: 10, - spreadPerc: 1, - shareTxForMovement: 5e3, - symbol: "mock", - }; - - beforeEach(function() { - function construct() { - stock = new _src_StockMarket_Stock__WEBPACK_IMPORTED_MODULE_2__["Stock"](ctorParams); - } - - expect(construct).to.not.throw(); - }); - - describe("Stock Class", function() { - describe("constructor", function() { - it("should have default parameters", function() { - let defaultStock; - function construct() { - defaultStock = new _src_StockMarket_Stock__WEBPACK_IMPORTED_MODULE_2__["Stock"](); - } - - expect(construct).to.not.throw(); - expect(defaultStock.name).to.equal(""); - }); - - it("should properly initialize props from parameters", function() { - expect(stock.name).to.equal(ctorParams.name); - expect(stock.symbol).to.equal(ctorParams.symbol); - expect(stock.price).to.equal(ctorParams.initPrice); - expect(stock.lastPrice).to.equal(ctorParams.initPrice); - 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.maxShares).to.be.below(stock.totalShares); - expect(stock.spreadPerc).to.equal(ctorParams.spreadPerc); - expect(stock.priceMovementPerc).to.be.a("number"); - expect(stock.priceMovementPerc).to.be.at.most(stock.spreadPerc); - expect(stock.priceMovementPerc).to.be.at.least(0); - }); - - it ("should properly initialize props from range-values", function() { - let stock; - const params = { - b: true, - initPrice: { - max: 10e3, - min: 1e3, - }, - marketCap: 5e9, - mv: { - divisor: 100, - max: 150, - min: 50, - }, - name: "MockStock", - otlkMag: 10, - spreadPerc: { - divisor: 10, - max: 10, - min: 1, - }, - shareTxForMovement: { - max: 10e3, - min: 5e3, - }, - symbol: "mock", - }; - - function construct() { - stock = new _src_StockMarket_Stock__WEBPACK_IMPORTED_MODULE_2__["Stock"](params); - } - - expect(construct).to.not.throw(); - expect(stock.price).to.be.within(params.initPrice.min, params.initPrice.max); - expect(stock.mv).to.be.within(params.mv.min / params.mv.divisor, params.mv.max / params.mv.divisor); - expect(stock.spreadPerc).to.be.within(params.spreadPerc.min / params.spreadPerc.divisor, params.spreadPerc.max / params.spreadPerc.divisor); - expect(stock.shareTxForMovement).to.be.within(params.shareTxForMovement.min, params.shareTxForMovement.max); - }); - - it("should round the 'totalShare' prop to the nearest 100k", function() { - expect(stock.totalShares % 100e3).to.equal(0); - }); - }); - - describe("#changePrice()", function() { - it("should set both the last price and current price properties", function() { - const newPrice = 20e3; - stock.changePrice(newPrice); - expect(stock.lastPrice).to.equal(ctorParams.initPrice); - expect(stock.price).to.equal(newPrice); - }); - }); - - describe("#getAskPrice()", function() { - it("should return the price increased by spread percentage", function() { - const perc = stock.spreadPerc / 100; - expect(perc).to.be.at.most(1); - expect(perc).to.be.at.least(0); - - const expected = stock.price * (1 + perc); - expect(stock.getAskPrice()).to.equal(expected); - }); - }); - - describe("#getBidPrice()", function() { - it("should return the price decreased by spread percentage", function() { - const perc = stock.spreadPerc / 100; - expect(perc).to.be.at.most(1); - expect(perc).to.be.at.least(0); - - const expected = stock.price * (1 - perc); - expect(stock.getBidPrice()).to.equal(expected); - }); - }); - }); - - /* - // TODO These tests fail due to circular dependency errors - describe("StockMarket object", function() { - describe("Initialization", function() { - // Keeps track of initialized stocks. Contains their symbols - const stocks = []; - - before(function() { - expect(initStockMarket).to.not.throw(); - expect(initSymbolToStockMap).to.not.throw(); - }); - - it("should have Stock objects", function() { - for (const prop in StockMarket) { - const stock = StockMarket[prop]; - if (stock instanceof Stock) { - stocks.push(stock.symbol); - } - } - - // We'll just check that there are some stocks - expect(stocks.length).to.be.at.least(1); - }); - - it("should have an order book in the 'Orders' property", function() { - expect(StockMarket).to.have.property("Orders"); - - const orderbook = StockMarket["Orders"]; - for (const symbol of stocks) { - const ordersForStock = orderbook[symbol]; - expect(ordersForStock).to.be.an("array"); - expect(ordersForStock.length).to.equal(0); - } - }); - - it("should have properties for managing game cycles", function() { - expect(StockMarket).to.have.property("storedCycles"); - expect(StockMarket).to.have.property("lastUpdate"); - }); - }); - - // Because 'StockMarket' is a global object, the effects of initialization from - // the block above should still stand - describe("Deletion", function() { - it("should set StockMarket to be an empty object", function() { - expect(StockMarket).to.be.an("object").that.is.not.empty; - deleteStockMarket(); - expect(StockMarket).to.be.an("object").that.is.empty; - }); - }); - - // Reset stock market for each test - beforeEach(function() { - deleteStockMarket(); - initStockMarket(); - initSymbolToStockMap(); - }); - - it("should properly initialize", function() { - - }); - }); - */ - - describe("Transaction Cost Calculator Functions", function() { - describe("getBuyTransactionCost()", function() { - it("should fail on invalid 'stock' argument", function() { - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getBuyTransactionCost"])({}, 10, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(res).to.equal(null); - }); - - it("should fail on invalid 'shares' arg", function() { - let res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getBuyTransactionCost"])(stock, NaN, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(res).to.equal(null); - - res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getBuyTransactionCost"])(stock, -1, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(res).to.equal(null); - }); - - it("should properly evaluate LONG transactions that doesn't trigger a price movement", function() { - const shares = ctorParams.shareTxForMovement / 2; - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getBuyTransactionCost"])(stock, shares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(res).to.equal(shares * stock.getAskPrice() + commission); - }); - - it("should properly evaluate SHORT transactions that doesn't trigger a price movement", function() { - const shares = ctorParams.shareTxForMovement / 2; - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getBuyTransactionCost"])(stock, shares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - expect(res).to.equal(shares * stock.getBidPrice() + commission); - }); - - it("should properly evaluate LONG transactions that trigger price movements", function() { - const sharesPerMvmt = ctorParams.shareTxForMovement; - const shares = sharesPerMvmt * 3; - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getBuyTransactionCost"])(stock, shares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - - // Calculate expected cost - const secondPrice = stock.getAskPrice() * Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["calculateIncreasingPriceMovement"])(stock); - const thirdPrice = secondPrice * Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["calculateIncreasingPriceMovement"])(stock); - let expected = (sharesPerMvmt * stock.getAskPrice()) + (sharesPerMvmt * secondPrice) + (sharesPerMvmt * thirdPrice); - - expect(res).to.equal(expected + commission); - }); - - it("should properly evaluate SHORT transactions that trigger price movements", function() { - const sharesPerMvmt = ctorParams.shareTxForMovement; - const shares = sharesPerMvmt * 3; - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getBuyTransactionCost"])(stock, shares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - - // Calculate expected cost - const secondPrice = stock.getBidPrice() * Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["calculateDecreasingPriceMovement"])(stock); - const thirdPrice = secondPrice * Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["calculateDecreasingPriceMovement"])(stock); - let expected = (sharesPerMvmt * stock.getBidPrice()) + (sharesPerMvmt * secondPrice) + (sharesPerMvmt * thirdPrice); - - expect(res).to.equal(expected + commission); - }); - - it("should cap the 'shares' argument at the stock's maximum number of shares", function() { - const maxRes = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getBuyTransactionCost"])(stock, stock.maxShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - const exceedRes = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getBuyTransactionCost"])(stock, stock.maxShares * 10, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(maxRes).to.equal(exceedRes); - }); - }); - - describe("getSellTransactionGain()", function() { - it("should fail on invalid 'stock' argument", function() { - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getSellTransactionGain"])({}, 10, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(res).to.equal(null); - }); - - it("should fail on invalid 'shares' arg", function() { - let res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getSellTransactionGain"])(stock, NaN, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(res).to.equal(null); - - res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getSellTransactionGain"])(stock, -1, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(res).to.equal(null); - }); - - it("should properly evaluate LONG transactions that doesn't trigger a price movement", function() { - const shares = ctorParams.shareTxForMovement / 2; - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getSellTransactionGain"])(stock, shares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - const expected = shares * stock.getBidPrice() - commission; - expect(res).to.equal(expected); - }); - - it("should properly evaluate SHORT transactions that doesn't trigger a price movement", function() { - // We need to set this property in order to calculate gains from short position - stock.playerAvgShortPx = stock.price * 2; - - const shares = ctorParams.shareTxForMovement / 2; - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getSellTransactionGain"])(stock, shares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - const expected = (shares * stock.playerAvgShortPx) + (shares * (stock.playerAvgShortPx - stock.getAskPrice())) - commission; - expect(res).to.equal(expected); - }); - - it("should properly evaluate LONG transactions that trigger price movements", function() { - const sharesPerMvmt = ctorParams.shareTxForMovement; - const shares = sharesPerMvmt * 3; - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getSellTransactionGain"])(stock, shares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - - // Calculated expected gain - const mvmt = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["calculateDecreasingPriceMovement"])(stock); - const secondPrice = stock.getBidPrice() * mvmt; - const thirdPrice = secondPrice * mvmt; - const expected = (sharesPerMvmt * stock.getBidPrice()) + (sharesPerMvmt * secondPrice) + (sharesPerMvmt * thirdPrice); - - expect(res).to.equal(expected - commission); - }); - - it("should properly evaluate SHORT transactions that trigger price movements", function() { - // We need to set this property in order to calculate gains from short position - stock.playerAvgShortPx = stock.price * 2; - - const sharesPerMvmt = ctorParams.shareTxForMovement; - const shares = sharesPerMvmt * 3; - const res = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getSellTransactionGain"])(stock, shares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - - // Calculate expected gain - const mvmt = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["calculateIncreasingPriceMovement"])(stock); - const secondPrice = stock.getAskPrice() * mvmt; - const thirdPrice = secondPrice * mvmt; - function getGainForPrice(thisPrice) { - const origCost = sharesPerMvmt * stock.playerAvgShortPx; - return origCost + ((stock.playerAvgShortPx - thisPrice) * sharesPerMvmt); - } - const expected = getGainForPrice(stock.getAskPrice()) + getGainForPrice(secondPrice) + getGainForPrice(thirdPrice); - - expect(res).to.equal(expected - commission); - }); - - it("should cap the 'shares' argument at the stock's maximum number of shares", function() { - const maxRes = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getSellTransactionGain"])(stock, stock.maxShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - const exceedRes = Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["getSellTransactionGain"])(stock, stock.maxShares * 10, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(maxRes).to.equal(exceedRes); - }); - }); - }); - - describe("Price Movement Processor Functions", function() { - // N = 1 is the original price - function getNthPriceIncreasing(origPrice, n) { - let price = origPrice; - for (let i = 1; i < n; ++i) { - price *= Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["calculateIncreasingPriceMovement"])(stock); - } - - return price; - } - - // N = 1 is the original price - function getNthPriceDecreasing(origPrice, n) { - let price = origPrice; - for (let i = 1; i < n; ++i) { - price *= Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["calculateDecreasingPriceMovement"])(stock); - } - - return price; - } - - // N = 1 is the original forecast - function getNthForecast(origForecast, n) { - return origForecast - _src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["forecastChangePerPriceMovement"] * (n - 1); - } - - describe("processBuyTransactionPriceMovement()", function() { - const noMvmtShares = Math.round(ctorParams.shareTxForMovement / 2.2); - const mvmtShares = ctorParams.shareTxForMovement * 3 + noMvmtShares; - - it("should do nothing on invalid 'stock' argument", function() { - const oldPrice = stock.price; - const oldTracker = stock.shareTxUntilMovement; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])({}, mvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(stock.price).to.equal(oldPrice); - expect(stock.shareTxUntilMovement).to.equal(oldTracker); - }); - - it("should do nothing on invalid 'shares' arg", function() { - const oldPrice = stock.price; - const oldTracker = stock.shareTxUntilMovement; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, NaN, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(stock.price).to.equal(oldPrice); - expect(stock.shareTxUntilMovement).to.equal(oldTracker); - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, -1, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(stock.price).to.equal(oldPrice); - expect(stock.shareTxUntilMovement).to.equal(oldTracker); - }); - - it("should properly evaluate a LONG transaction that doesn't trigger a price movement", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, noMvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(stock.price).to.equal(oldPrice); - expect(stock.otlkMag).to.equal(oldForecast); - expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares); - }); - - it("should properly evaluate a SHORT transaction that doesn't trigger a price movement", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, noMvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - expect(stock.price).to.equal(oldPrice); - expect(stock.otlkMag).to.equal(oldForecast); - expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares); - }); - - it("should properly evaluate LONG transactions that trigger price movements", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, mvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate SHORT transactions that trigger price movements", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, mvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate LONG transactions of exactly 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, stock.shareTxForMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate LONG transactions that total to 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, Math.round(stock.shareTxForMovement / 2), _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, stock.shareTxUntilMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate LONG transactions that are a multiple of 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, 3 * stock.shareTxForMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate SHORT transactions of exactly 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, stock.shareTxForMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate SHORT transactions that total to 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, Math.round(stock.shareTxForMovement / 2), _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, stock.shareTxUntilMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate SHORT transactions that are a multiple of 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processBuyTransactionPriceMovement"])(stock, 3 * stock.shareTxForMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - }); - - describe("processSellTransactionPriceMovement()", function() { - const noMvmtShares = Math.round(ctorParams.shareTxForMovement / 2.2); - const mvmtShares = ctorParams.shareTxForMovement * 3 + noMvmtShares; - - it("should do nothing on invalid 'stock' argument", function() { - const oldPrice = stock.price; - const oldTracker = stock.shareTxUntilMovement; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])({}, mvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(stock.price).to.equal(oldPrice); - expect(stock.shareTxUntilMovement).to.equal(oldTracker); - }); - - it("should do nothing on invalid 'shares' arg", function() { - const oldPrice = stock.price; - const oldTracker = stock.shareTxUntilMovement; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, NaN, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(stock.price).to.equal(oldPrice); - expect(stock.shareTxUntilMovement).to.equal(oldTracker); - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, -1, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(stock.price).to.equal(oldPrice); - expect(stock.shareTxUntilMovement).to.equal(oldTracker); - }); - - it("should properly evaluate a LONG transaction that doesn't trigger a price movement", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, noMvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - expect(stock.price).to.equal(oldPrice); - expect(stock.otlkMag).to.equal(oldForecast); - expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares); - }); - - it("should properly evaluate a SHORT transaction that doesn't trigger a price movement", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, noMvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - expect(stock.price).to.equal(oldPrice); - expect(stock.otlkMag).to.equal(oldForecast); - expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares); - }); - - it("should properly evaluate LONG transactions that trigger price movements", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, mvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate SHORT transactions that trigger price movements", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, mvmtShares, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate LONG transactions of exactly 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, stock.shareTxForMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate LONG transactions that total to 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, Math.round(stock.shareTxForMovement / 2), _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, stock.shareTxUntilMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate LONG transactions that are a multiple of 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, 3 * stock.shareTxForMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate SHORT transactions of exactly 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, stock.shareTxForMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate SHORT transactions that total to 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, Math.round(stock.shareTxForMovement / 2), _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, stock.shareTxUntilMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - - it("should properly evaluate SHORT transactions that are a multiple of 'shareTxForMovement' shares", function() { - const oldPrice = stock.price; - const oldForecast = stock.otlkMag; - - Object(_src_StockMarket_StockMarketHelpers__WEBPACK_IMPORTED_MODULE_3__["processSellTransactionPriceMovement"])(stock, 3 * stock.shareTxForMovement, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["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); - }); - }); - }); - - describe("Order Class", function() { - it("should throw on invalid arguments", function() { - function invalid1() { - return new _src_StockMarket_Order__WEBPACK_IMPORTED_MODULE_1__["Order"]({}, 1, 1, _src_StockMarket_data_OrderTypes__WEBPACK_IMPORTED_MODULE_4__["OrderTypes"].LimitBuy, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Long); - } - function invalid2() { - return new _src_StockMarket_Order__WEBPACK_IMPORTED_MODULE_1__["Order"]("FOO", "z", 0, _src_StockMarket_data_OrderTypes__WEBPACK_IMPORTED_MODULE_4__["OrderTypes"].LimitBuy, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - } - function invalid3() { - return new _src_StockMarket_Order__WEBPACK_IMPORTED_MODULE_1__["Order"]("FOO", 1, {}, _src_StockMarket_data_OrderTypes__WEBPACK_IMPORTED_MODULE_4__["OrderTypes"].LimitBuy, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - } - function invalid4() { - return new _src_StockMarket_Order__WEBPACK_IMPORTED_MODULE_1__["Order"]("FOO", 1, NaN, _src_StockMarket_data_OrderTypes__WEBPACK_IMPORTED_MODULE_4__["OrderTypes"].LimitBuy, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - } - function invalid5() { - return new _src_StockMarket_Order__WEBPACK_IMPORTED_MODULE_1__["Order"]("FOO", NaN, 0, _src_StockMarket_data_OrderTypes__WEBPACK_IMPORTED_MODULE_4__["OrderTypes"].LimitBuy, _src_StockMarket_data_PositionTypes__WEBPACK_IMPORTED_MODULE_5__["PositionTypes"].Short); - } - - expect(invalid1).to.throw(); - expect(invalid2).to.throw(); - expect(invalid3).to.throw(); - expect(invalid4).to.throw(); - expect(invalid5).to.throw(); - }); - }); - - describe("Order Processing", function() { - - }); -}); - - -/***/ }), - -/***/ 206: -/*!*****************************************************!*\ - !*** ./test/Netscript/StaticRamCalculationTests.js ***! - \*****************************************************/ -/*! no exports provided */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var _src_Netscript_RamCostGenerator__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../src/Netscript/RamCostGenerator */ 10); -/* harmony import */ var _src_Netscript_RamCostGenerator__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_src_Netscript_RamCostGenerator__WEBPACK_IMPORTED_MODULE_0__); -/** - * 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 { 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() { - it("should run", function() { - expect(1).to.equal(1); - }); -}); - - -/***/ }), - -/***/ 23: -/*!***********************************************!*\ - !*** ./src/StockMarket/data/PositionTypes.ts ***! - \***********************************************/ -/*! no static exports found */ -/*! all exports used */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var PositionTypes; -(function (PositionTypes) { - PositionTypes["Long"] = "L"; - PositionTypes["Short"] = "S"; -})(PositionTypes = exports.PositionTypes || (exports.PositionTypes = {})); - - -/***/ }), - -/***/ 27: -/*!***********************************************!*\ - !*** ./src/StockMarket/StockMarketHelpers.ts ***! - \***********************************************/ -/*! no static exports found */ -/*! all exports used */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const Stock_1 = __webpack_require__(/*! ./Stock */ 66); -const PositionTypes_1 = __webpack_require__(/*! ./data/PositionTypes */ 23); -const Constants_1 = __webpack_require__(/*! ../Constants */ 8); -// Amount by which a stock's forecast changes during each price movement -exports.forecastChangePerPriceMovement = 0.1; -/** - * Given a stock, calculates the amount by which the stock price is multiplied - * for an 'upward' price movement. This does not actually increase the stock's price, - * just calculates the multiplier - * @param {Stock} stock - Stock for price movement - * @returns {number | null} Number by which stock's price should be multiplied. Null for invalid args - */ -function calculateIncreasingPriceMovement(stock) { - if (!(stock instanceof Stock_1.Stock)) { - return null; - } - return (1 + (stock.priceMovementPerc / 100)); -} -exports.calculateIncreasingPriceMovement = calculateIncreasingPriceMovement; -/** - * Given a stock, calculates the amount by which the stock price is multiplied - * for a "downward" price movement. This does not actually increase the stock's price, - * just calculates the multiplier - * @param {Stock} stock - Stock for price movement - * @returns {number | null} Number by which stock's price should be multiplied. Null for invalid args - */ -function calculateDecreasingPriceMovement(stock) { - if (!(stock instanceof Stock_1.Stock)) { - return null; - } - return (1 - (stock.priceMovementPerc / 100)); -} -exports.calculateDecreasingPriceMovement = calculateDecreasingPriceMovement; -/** - * Calculate the total cost of a "buy" transaction. This accounts for spread, - * price movements, and commission. - * @param {Stock} stock - Stock being purchased - * @param {number} shares - Number of shares being transacted - * @param {PositionTypes} posType - Long or short position - * @returns {number | null} Total transaction cost. Returns null for an invalid transaction - */ -function getBuyTransactionCost(stock, shares, posType) { - if (isNaN(shares) || shares <= 0 || !(stock instanceof Stock_1.Stock)) { - return null; - } - // Cap the 'shares' arg at the stock's maximum shares. This'll prevent - // hanging in the case when a really big number is passed in - shares = Math.min(shares, stock.maxShares); - const isLong = (posType === PositionTypes_1.PositionTypes.Long); - // If the number of shares doesn't trigger a price movement, its a simple calculation - if (shares <= stock.shareTxUntilMovement) { - if (isLong) { - return (shares * stock.getAskPrice()) + Constants_1.CONSTANTS.StockMarketCommission; - } - else { - return (shares * stock.getBidPrice()) + Constants_1.CONSTANTS.StockMarketCommission; - } - } - // Calculate how many iterations of price changes we need to account for - let remainingShares = shares - stock.shareTxUntilMovement; - 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); - const increasingMvmt = calculateIncreasingPriceMovement(stock); - const decreasingMvmt = calculateDecreasingPriceMovement(stock); - function processPriceMovement() { - if (isLong) { - currPrice *= increasingMvmt; - } - else { - currPrice *= decreasingMvmt; - } - } - for (let i = 1; i < numIterations; ++i) { - processPriceMovement(); - const amt = Math.min(stock.shareTxForMovement, remainingShares); - totalCost += (amt * currPrice); - remainingShares -= amt; - } - return totalCost + Constants_1.CONSTANTS.StockMarketCommission; -} -exports.getBuyTransactionCost = getBuyTransactionCost; -/** - * Processes a buy transaction's resulting price AND forecast movement. - * @param {Stock} stock - Stock being purchased - * @param {number} shares - Number of shares being transacted - * @param {PositionTypes} posType - Long or short position - */ -function processBuyTransactionPriceMovement(stock, shares, posType) { - if (isNaN(shares) || shares <= 0 || !(stock instanceof Stock_1.Stock)) { - return; - } - // Cap the 'shares' arg at the stock's maximum shares. This'll prevent - // hanging in the case when a really big number is passed in - shares = Math.min(shares, stock.maxShares); - const isLong = (posType === PositionTypes_1.PositionTypes.Long); - let currPrice = stock.price; - function processPriceMovement() { - if (isLong) { - currPrice *= calculateIncreasingPriceMovement(stock); - } - else { - currPrice *= calculateDecreasingPriceMovement(stock); - } - } - // No price/forecast movement - if (shares <= stock.shareTxUntilMovement) { - stock.shareTxUntilMovement -= shares; - if (stock.shareTxUntilMovement <= 0) { - stock.shareTxUntilMovement = stock.shareTxForMovement; - processPriceMovement(); - stock.changePrice(currPrice); - stock.otlkMag -= (exports.forecastChangePerPriceMovement); - } - return; - } - // Calculate how many iterations of price changes we need to account for - let remainingShares = shares - stock.shareTxUntilMovement; - 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(); - } - stock.changePrice(currPrice); - // Forecast always decreases in magnitude - const forecastChange = Math.min(5, exports.forecastChangePerPriceMovement * (numIterations - 1)); - stock.otlkMag -= forecastChange; - if (stock.otlkMag < 0) { - stock.b = !stock.b; - stock.otlkMag = Math.abs(stock.otlkMag); - } -} -exports.processBuyTransactionPriceMovement = processBuyTransactionPriceMovement; -/** - * Calculate the TOTAL amount of money gained from a sale (NOT net profit). This accounts - * for spread, price movements, and commission. - * @param {Stock} stock - Stock being sold - * @param {number} shares - Number of sharse being transacted - * @param {PositionTypes} posType - Long or short position - * @returns {number | null} Amount of money gained from transaction. Returns null for an invalid transaction - */ -function getSellTransactionGain(stock, shares, posType) { - if (isNaN(shares) || shares <= 0 || !(stock instanceof Stock_1.Stock)) { - return null; - } - // Cap the 'shares' arg at the stock's maximum shares. This'll prevent - // hanging in the case when a really big number is passed in - shares = Math.min(shares, stock.maxShares); - const isLong = (posType === PositionTypes_1.PositionTypes.Long); - // If the number of shares doesn't trigger a price mvoement, its a simple calculation - if (shares <= stock.shareTxUntilMovement) { - if (isLong) { - return (shares * stock.getBidPrice()) - Constants_1.CONSTANTS.StockMarketCommission; - } - else { - // Calculating gains for a short position requires calculating the profit made - const origCost = shares * stock.playerAvgShortPx; - const profit = ((stock.playerAvgShortPx - stock.getAskPrice()) * shares) - Constants_1.CONSTANTS.StockMarketCommission; - return origCost + profit; - } - } - // Calculate how many iterations of price changes we need to account for - let remainingShares = shares - stock.shareTxUntilMovement; - let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement); - // Helper function to calculate gain for a single iteration - function calculateGain(thisPrice, thisShares) { - if (isLong) { - return thisShares * thisPrice; - } - else { - const origCost = thisShares * stock.playerAvgShortPx; - const profit = ((stock.playerAvgShortPx - thisPrice) * thisShares); - return origCost + profit; - } - } - // The initial cost calculation takes care of the first "iteration" - let currPrice = isLong ? stock.getBidPrice() : stock.getAskPrice(); - let totalGain = calculateGain(currPrice, stock.shareTxUntilMovement); - for (let i = 1; i < numIterations; ++i) { - // Price movement - if (isLong) { - currPrice *= calculateDecreasingPriceMovement(stock); - } - else { - currPrice *= calculateIncreasingPriceMovement(stock); - } - const amt = Math.min(stock.shareTxForMovement, remainingShares); - totalGain += calculateGain(currPrice, amt); - remainingShares -= amt; - } - return totalGain - Constants_1.CONSTANTS.StockMarketCommission; -} -exports.getSellTransactionGain = getSellTransactionGain; -/** - * Processes a sell transaction's resulting price movement - * @param {Stock} stock - Stock being sold - * @param {number} shares - Number of sharse being transacted - * @param {PositionTypes} posType - Long or short position - */ -function processSellTransactionPriceMovement(stock, shares, posType) { - if (isNaN(shares) || shares <= 0 || !(stock instanceof Stock_1.Stock)) { - return; - } - // Cap the 'shares' arg at the stock's maximum shares. This'll prevent - // hanging in the case when a really big number is passed in - shares = Math.min(shares, stock.maxShares); - const isLong = (posType === PositionTypes_1.PositionTypes.Long); - let currPrice = stock.price; - function processPriceMovement() { - if (isLong) { - currPrice *= calculateDecreasingPriceMovement(stock); - } - else { - currPrice *= calculateIncreasingPriceMovement(stock); - } - } - // No price/forecast movement - if (shares <= stock.shareTxUntilMovement) { - stock.shareTxUntilMovement -= shares; - if (stock.shareTxUntilMovement <= 0) { - stock.shareTxUntilMovement = stock.shareTxForMovement; - processPriceMovement(); - stock.changePrice(currPrice); - stock.otlkMag -= (exports.forecastChangePerPriceMovement); - } - return; - } - // Calculate how many iterations of price changes we need to account for - let remainingShares = shares - stock.shareTxUntilMovement; - 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(); - } - stock.changePrice(currPrice); - // Forecast always decreases in magnitude - const forecastChange = Math.min(5, exports.forecastChangePerPriceMovement * (numIterations - 1)); - stock.otlkMag -= forecastChange; - if (stock.otlkMag < 0) { - stock.b = !stock.b; - stock.otlkMag = Math.abs(stock.otlkMag); - } -} -exports.processSellTransactionPriceMovement = processSellTransactionPriceMovement; -/** - * Calculate the maximum number of shares of a stock that can be purchased. - * Handles mid-transaction price movements, both L and S positions, etc. - * Used for the "Buy Max" button in the UI - * @param {Stock} stock - Stock being purchased - * @param {PositionTypes} posType - Long or short position - * @param {number} money - Amount of money player has - * @returns maximum number of shares that the player can purchase - */ -function calculateBuyMaxAmount(stock, posType, money) { - if (!(stock instanceof Stock_1.Stock)) { - return 0; - } - const isLong = (posType === PositionTypes_1.PositionTypes.Long); - const increasingMvmt = calculateIncreasingPriceMovement(stock); - const decreasingMvmt = calculateDecreasingPriceMovement(stock); - if (increasingMvmt == null || decreasingMvmt == null) { - return 0; - } - let remainingMoney = money - Constants_1.CONSTANTS.StockMarketCommission; - let currPrice = isLong ? stock.getAskPrice() : stock.getBidPrice(); - // No price movement - const firstIterationCost = stock.shareTxUntilMovement * 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; - remainingMoney -= firstIterationCost; - for (let i = 0; i < 10e3; ++i) { - if (isLong) { - currPrice *= increasingMvmt; - } - else { - currPrice *= decreasingMvmt; - } - const affordableShares = Math.floor(remainingMoney / currPrice); - const actualShares = Math.min(stock.shareTxForMovement, affordableShares); - // Can't afford any more, so we're done - if (actualShares <= 0) { - break; - } - numShares += actualShares; - let cost = actualShares * currPrice; - remainingMoney -= cost; - if (remainingMoney <= 0) { - break; - } - } - return Math.floor(numShares); -} -exports.calculateBuyMaxAmount = calculateBuyMaxAmount; - - -/***/ }), - -/***/ 300: -/*!***********************!*\ - !*** ./test/index.js ***! - \***********************/ -/*! no exports provided */ -/*! all exports used */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _Netscript_StaticRamCalculationTests__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Netscript/StaticRamCalculationTests */ 206); -/* harmony import */ var _StockMarketTests__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./StockMarketTests */ 205); - - - - -/***/ }), - -/***/ 54: -/*!********************************************!*\ - !*** ./src/StockMarket/data/OrderTypes.ts ***! - \********************************************/ -/*! no static exports found */ -/*! all exports used */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -var OrderTypes; -(function (OrderTypes) { - OrderTypes["LimitBuy"] = "Limit Buy Order"; - OrderTypes["LimitSell"] = "Limit Sell Order"; - OrderTypes["StopBuy"] = "Stop Buy Order"; - OrderTypes["StopSell"] = "Stop Sell Order"; -})(OrderTypes = exports.OrderTypes || (exports.OrderTypes = {})); - - -/***/ }), - -/***/ 66: -/*!**********************************!*\ - !*** ./src/StockMarket/Stock.ts ***! - \**********************************/ -/*! no static exports found */ -/*! all exports used */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -const JSONReviver_1 = __webpack_require__(/*! ../../utils/JSONReviver */ 16); -const getRandomInt_1 = __webpack_require__(/*! ../../utils/helpers/getRandomInt */ 15); -const defaultConstructorParams = { - b: true, - initPrice: 10e3, - marketCap: 1e12, - mv: 1, - name: "", - otlkMag: 0, - spreadPerc: 0, - shareTxForMovement: 1e6, - symbol: "", -}; -// Helper function that convert a IMinMaxRange to a number -function toNumber(n) { - let value; - switch (typeof n) { - case "number": { - return n; - } - case "object": { - const range = n; - value = getRandomInt_1.getRandomInt(range.min, range.max); - break; - } - default: - throw Error(`Do not know how to convert the type '${typeof n}' to a number`); - } - if (typeof n === "object" && typeof n.divisor === "number") { - return value / n.divisor; - } - return value; -} -/** - * Represents the valuation of a company in the World Stock Exchange. - */ -class Stock { - /** - * Initializes a Stock from a JSON save state - */ - static fromJSON(value) { - return JSONReviver_1.Generic_fromJSON(Stock, value.data); - } - constructor(p = 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_1.getRandomInt(this.price * 1e3, this.price * 25e3); - this.spreadPerc = toNumber(p.spreadPerc); - this.priceMovementPerc = this.spreadPerc / (getRandomInt_1.getRandomInt(10, 30) / 10); - this.shareTxForMovement = toNumber(p.shareTxForMovement); - this.shareTxUntilMovement = this.shareTxForMovement; - // Total shares is determined by market cap, and is rounded to nearest 100k - let totalSharesUnrounded = (p.marketCap / this.price); - this.totalShares = Math.round(totalSharesUnrounded / 1e5) * 1e5; - // Max Shares (Outstanding shares) is a percentage of total shares - const outstandingSharePercentage = 0.2; - this.maxShares = Math.round((this.totalShares * outstandingSharePercentage) / 1e5) * 1e5; - } - changePrice(newPrice) { - this.lastPrice = this.price; - this.price = newPrice; - } - /** - * Return the price at which YOUR stock is bought (market ask price). Accounts for spread - */ - getAskPrice() { - return this.price * (1 + (this.spreadPerc / 100)); - } - /** - * Return the price at which YOUR stock is sold (market bid price). Accounts for spread - */ - getBidPrice() { - return this.price * (1 - (this.spreadPerc / 100)); - } - /** - * Serialize the Stock to a JSON save state. - */ - toJSON() { - return JSONReviver_1.Generic_toJSON("Stock", this); - } -} -exports.Stock = Stock; -JSONReviver_1.Reviver.constructors.Stock = Stock; - - -/***/ }), - -/***/ 8: -/*!**************************!*\ - !*** ./src/Constants.ts ***! - \**************************/ -/*! no static exports found */ -/*! all exports used */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -exports.CONSTANTS = { - Version: "0.46.3", - /** 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 - * the player will have this level assuming no multipliers. Multipliers can cause skills to go above this. - */ - MaxSkillLevel: 975, - // Milliseconds per game cycle - MilliPerCycle: 200, - // How much reputation is needed to join a megacorporation's faction - CorpFactionRepRequirement: 200e3, - // Base RAM costs - BaseCostFor1GBOfRamHome: 32000, - BaseCostFor1GBOfRamServer: 55000, - // Cost to travel to another city - TravelCost: 200e3, - // Faction and Company favor-related things - BaseFavorToDonate: 150, - DonateMoneyToRepDivisor: 1e6, - FactionReputationToFavorBase: 500, - FactionReputationToFavorMult: 1.02, - CompanyReputationToFavorBase: 500, - CompanyReputationToFavorMult: 1.02, - // NeuroFlux Governor Augmentation cost multiplier - NeuroFluxGovernorLevelMult: 1.14, - NumNetscriptPorts: 20, - // Server-related constants - HomeComputerMaxRam: 1073741824, - ServerBaseGrowthRate: 1.03, - ServerMaxGrowthRate: 1.0035, - ServerFortifyAmount: 0.002, - ServerWeakenAmount: 0.05, - PurchasedServerLimit: 25, - PurchasedServerMaxRam: 1048576, - // Augmentation Constants - AugmentationCostMultiplier: 5, - AugmentationRepMultiplier: 2.5, - MultipleAugMultiplier: 1.9, - // TOR Router - TorRouterCost: 200e3, - // Infiltration - InfiltrationBribeBaseAmount: 100e3, - InfiltrationMoneyValue: 5e3, - InfiltrationRepValue: 1.4, - InfiltrationExpPow: 0.8, - // Stock market - WSEAccountCost: 200e6, - TIXAPICost: 5e9, - MarketData4SCost: 1e9, - MarketDataTixApi4SCost: 25e9, - StockMarketCommission: 100e3, - // Hospital/Health - HospitalCostPerHp: 100e3, - // Intelligence-related constants - IntelligenceCrimeWeight: 0.05, - IntelligenceInfiltrationWeight: 0.1, - IntelligenceCrimeBaseExpGain: 0.001, - IntelligenceProgramBaseExpGain: 500, - IntelligenceTerminalHackBaseExpGain: 200, - IntelligenceSingFnBaseExpGain: 0.002, - IntelligenceClassBaseExpGain: 0.000001, - IntelligenceHackingMissionBaseExpGain: 0.03, - // Hacking Missions - // TODO Move this into Hacking Mission implementation - HackingMissionRepToDiffConversion: 10000, - HackingMissionRepToRewardConversion: 7, - HackingMissionSpamTimeIncrease: 25000, - HackingMissionTransferAttackIncrease: 1.05, - HackingMissionMiscDefenseIncrease: 1.05, - HackingMissionDifficultyToHacking: 135, - HackingMissionHowToPlay: "Hacking missions are a minigame that, if won, will reward you with faction reputation.

" + - "In this game you control a set of Nodes and use them to try and defeat an enemy. Your Nodes " + - "are colored blue, while the enemy's are red. There are also other nodes on the map colored gray " + - "that initially belong to neither you nor the enemy. The goal of the game is " + - "to capture all of the enemy's Database nodes within the time limit. " + - "If you fail to do this, you will lose.

" + - "Each Node has three stats: Attack, Defense, and HP. There are five different actions that " + - "a Node can take:

" + - "Attack - Targets an enemy Node and lowers its HP. The effectiveness is determined by the owner's Attack, the Player's " + - "hacking level, and the enemy's defense.

" + - "Scan - Targets an enemy Node and lowers its Defense. The effectiveness is determined by the owner's Attack, the Player's hacking level, and the " + - "enemy's defense.

" + - "Weaken - Targets an enemy Node and lowers its Attack. The effectiveness is determined by the owner's Attack, the Player's hacking level, and the enemy's " + - "defense.

" + - "Fortify - Raises the Node's Defense. The effectiveness is determined by your hacking level.

" + - "Overflow - Raises the Node's Attack but lowers its Defense. The effectiveness is determined by your hacking level.

" + - "Note that when determining the effectiveness of the above actions, the TOTAL Attack or Defense of the team is used, not just the " + - "Attack/Defense of the individual Node that is performing the action.

" + - "To capture a Node, you must lower its HP down to 0.

" + - "There are six different types of Nodes:

" + - "CPU Core - These are your main Nodes that are used to perform actions. Capable of performing every action

" + - "Firewall - Nodes with high defense. These Nodes can 'Fortify'

" + - "Database - A special type of Node. The player's objective is to conquer all of the enemy's Database Nodes within " + - "the time limit. These Nodes cannot perform any actions

" + - "Spam - Conquering one of these Nodes will slow the enemy's trace, giving the player additional time to complete " + - "the mission. These Nodes cannot perform any actions

" + - "Transfer - Conquering one of these nodes will increase the Attack of all of your CPU Cores by a small fixed percentage. " + - "These Nodes are capable of performing every action except the 'Attack' action

" + - "Shield - Nodes with high defense. These Nodes can 'Fortify'

" + - "To assign an action to a Node, you must first select one of your Nodes. This can be done by simply clicking on it. Double-clicking " + - "a node will select all of your Nodes of the same type (e.g. select all CPU Core Nodes or all Transfer Nodes). Note that only Nodes " + - "that can perform actions (CPU Core, Transfer, Shield, Firewall) can be selected. Selected Nodes will be denoted with a white highlight. After selecting a Node or multiple Nodes, " + - "select its action using the Action Buttons near the top of the screen. Every action also has a corresponding keyboard " + - "shortcut.

" + - "For certain actions such as attacking, scanning, and weakening, the Node performing the action must have a target. To target " + - "another node, simply click-and-drag from the 'source' Node to a target. A Node can only have one target, and you can target " + - "any Node that is adjacent to one of your Nodes (immediately above, below, or to the side. NOT diagonal). Furthermore, only CPU Cores and Transfer Nodes " + - "can target, since they are the only ones that can perform the related actions. To remove a target, you can simply click on the line that represents " + - "the connection between one of your Nodes and its target. Alternatively, you can select the 'source' Node and click the 'Drop Connection' button, " + - "or press 'd'.

" + - "Other Notes:

" + - "-Whenever a miscellenaous Node (not owned by the player or enemy) is conquered, the defense of all remaining miscellaneous Nodes that " + - "are not actively being targeted will increase by a fixed percentage.

" + - "-Whenever a Node is conquered, its stats are significantly reduced

" + - "-Miscellaneous Nodes slowly raise their defense over time

" + - "-Nodes slowly regenerate health over time.", - // Time-related constants - MillisecondsPer20Hours: 72000000, - GameCyclesPer20Hours: 72000000 / 200, - MillisecondsPer10Hours: 36000000, - GameCyclesPer10Hours: 36000000 / 200, - MillisecondsPer8Hours: 28800000, - GameCyclesPer8Hours: 28800000 / 200, - MillisecondsPer4Hours: 14400000, - GameCyclesPer4Hours: 14400000 / 200, - MillisecondsPer2Hours: 7200000, - GameCyclesPer2Hours: 7200000 / 200, - MillisecondsPerHour: 3600000, - GameCyclesPerHour: 3600000 / 200, - MillisecondsPerHalfHour: 1800000, - GameCyclesPerHalfHour: 1800000 / 200, - MillisecondsPerQuarterHour: 900000, - GameCyclesPerQuarterHour: 900000 / 200, - MillisecondsPerFiveMinutes: 300000, - GameCyclesPerFiveMinutes: 300000 / 200, - // Player Work & Action - FactionWorkHacking: "Faction Hacking Work", - FactionWorkField: "Faction Field Work", - FactionWorkSecurity: "Faction Security Work", - WorkTypeCompany: "Working for Company", - WorkTypeCompanyPartTime: "Working for Company part-time", - WorkTypeFaction: "Working for Faction", - WorkTypeCreateProgram: "Working on Create a Program", - WorkTypeStudyClass: "Studying or Taking a class at university", - WorkTypeCrime: "Committing a crime", - ClassStudyComputerScience: "studying Computer Science", - ClassDataStructures: "taking a Data Structures course", - ClassNetworks: "taking a Networks course", - ClassAlgorithms: "taking an Algorithms course", - ClassManagement: "taking a Management course", - ClassLeadership: "taking a Leadership course", - ClassGymStrength: "training your strength at a gym", - ClassGymDefense: "training your defense at a gym", - ClassGymDexterity: "training your dexterity at a gym", - ClassGymAgility: "training your agility at a gym", - ClassDataStructuresBaseCost: 40, - ClassNetworksBaseCost: 80, - ClassAlgorithmsBaseCost: 320, - ClassManagementBaseCost: 160, - ClassLeadershipBaseCost: 320, - ClassGymBaseCost: 120, - CrimeShoplift: "shoplift", - CrimeRobStore: "rob a store", - CrimeMug: "mug someone", - CrimeLarceny: "commit larceny", - CrimeDrugs: "deal drugs", - CrimeBondForgery: "forge corporate bonds", - CrimeTraffickArms: "traffick illegal arms", - CrimeHomicide: "commit homicide", - CrimeGrandTheftAuto: "commit grand theft auto", - CrimeKidnap: "kidnap someone for ransom", - CrimeAssassination: "assassinate a high-profile target", - CrimeHeist: "pull off the ultimate heist", - // Coding Contract - // TODO Move this into Coding contract impelmentation? - CodingContractBaseFactionRepGain: 2500, - CodingContractBaseCompanyRepGain: 4000, - CodingContractBaseMoneyGain: 75e6, - // BitNode/Source-File related stuff - TotalNumBitNodes: 24, - LatestUpdate: ` - v0.47.0 - * 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 - - * Adjusted RAM costs of Netscript Singularity functions (mostly increased) - * Netscript Singularity functions no longer cost extra RAM outside of BitNode-4 - * Corporation employees no longer have an "age" stat - * 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 - ` -}; - - -/***/ }), - -/***/ 98: -/*!**********************************!*\ - !*** ./src/StockMarket/Order.ts ***! - \**********************************/ -/*! no static exports found */ -/*! exports used: Order */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Represents a Limit or Buy Order on the stock market. Does not represent - * a Market Order since those are just executed immediately - */ -const OrderTypes_1 = __webpack_require__(/*! ./data/OrderTypes */ 54); -const PositionTypes_1 = __webpack_require__(/*! ./data/PositionTypes */ 23); -const JSONReviver_1 = __webpack_require__(/*! ../../utils/JSONReviver */ 16); -class Order { - /** - * Initializes a Order from a JSON save state - */ - static fromJSON(value) { - return JSONReviver_1.Generic_fromJSON(Order, value.data); - } - constructor(stockSymbol = "", shares = 0, price = 0, typ = OrderTypes_1.OrderTypes.LimitBuy, pos = PositionTypes_1.PositionTypes.Long) { - // Validate arguments - let invalidArgs = false; - if (typeof shares !== "number" || typeof price !== "number") { - invalidArgs = true; - } - if (isNaN(shares) || isNaN(price)) { - invalidArgs = true; - } - if (typeof stockSymbol !== "string") { - invalidArgs = true; - } - if (invalidArgs) { - throw new Error(`Invalid constructor paramters for Order`); - } - this.stockSymbol = stockSymbol; - this.shares = shares; - this.price = price; - this.type = typ; - this.pos = pos; - } - /** - * Serialize the Order to a JSON save state. - */ - toJSON() { - return JSONReviver_1.Generic_toJSON("Order", this); - } -} -exports.Order = Order; -JSONReviver_1.Reviver.constructors.Order = Order; - - -/***/ }) - -/******/ }); -//# sourceMappingURL=tests.bundle.js.map \ No newline at end of file diff --git a/test/tests.bundle.js.map b/test/tests.bundle.js.map deleted file mode 100644 index 565ad9a66..000000000 --- a/test/tests.bundle.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/Netscript/RamCostGenerator.ts","webpack:///./utils/helpers/getRandomInt.ts","webpack:///./utils/JSONReviver.js","webpack:///./test/StockMarketTests.js","webpack:///./test/Netscript/StaticRamCalculationTests.js","webpack:///./src/StockMarket/data/PositionTypes.ts","webpack:///./src/StockMarket/StockMarketHelpers.ts","webpack:///./test/index.js","webpack:///./src/StockMarket/data/OrderTypes.ts","webpack:///./src/StockMarket/Stock.ts","webpack:///./src/Constants.ts","webpack:///./src/StockMarket/Order.ts"],"names":[],"mappings":"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A;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB;AACrB;AACA;AACA;AACA,qBAAqB;AACrB;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA,aAAa;AACb,SAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;;AAET;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,aAAa;AACb,SAAS;;AAET;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,aAAa;AACb,SAAS;AACT,KAAK;;AAEL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,aAAa;;AAEb;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA,aAAa;AACb,SAAS;;AAET;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;;AAET;AACA;AACA;AACA;AACA;AACA,SAAS;;AAET;;AAEA,SAAS;AACT,KAAK;AACL;;AAEA;AACA;AACA;AACA,gIAAoD;AACpD;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,aAAa;;AAEb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;;AAET;AACA;AACA,iIAAqD;AACrD;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;AACT,KAAK;;AAEL;AACA;AACA;AACA;AACA,2BAA2B,OAAO;AAClC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,2BAA2B,OAAO;AAClC;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA,iIAAqD;AACrD;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;;AAET;AACA;AACA;;AAEA;AACA;AACA;;AAEA,kIAAsD;AACtD;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,aAAa;AACb,SAAS;AACT,KAAK;;AAEL;AACA;AACA;AACA,0FAAmC;AACnC;AACA;AACA;AACA;AACA;AACA,oGAA6C;AAC7C;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,KAAK;;AAEL;;AAEA,KAAK;AACL,CAAC;;;;;;;;;;;;;AChqBD;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACqB;AACrB,UAAU,oBAAoB;;AAE9B;AACA;;AAEA;;AAEA;AACA;AACA;AACA,KAAK;AACL,CAAC;;;;;;;;;;;;;;;;AClBD,IAAY,aAGX;AAHD,WAAY,aAAa;IACrB,2BAAU;IACV,4BAAW;AACf,CAAC,EAHW,aAAa,GAAb,qBAAa,KAAb,qBAAa,QAGxB;;;;;;;;;;;;;;;;ACHD,uDAAgC;AAChC,4EAAqD;AACrD,+DAAyC;AAEzC,wEAAwE;AAC3D,sCAA8B,GAAG,GAAG,CAAC;AAElD;;;;;;GAMG;AACH,0CAAiD,KAAY;IACzD,IAAI,CAAC,CAAC,KAAK,YAA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","file":"test/tests.bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 300);\n","import { IMap } from \"../types\";\r\n\r\n// TODO remember to update RamCalculations.js and WorkerScript.js\r\n\r\n// RAM costs for Netscript functions\r\nexport const RamCostConstants: IMap = {\r\n ScriptBaseRamCost: 1.6,\r\n ScriptDomRamCost: 25,\r\n ScriptHackRamCost: 0.1,\r\n ScriptHackAnalyzeRamCost: 1,\r\n ScriptGrowRamCost: 0.15,\r\n ScriptGrowthAnalyzeRamCost: 1,\r\n ScriptWeakenRamCost: 0.15,\r\n ScriptScanRamCost: 0.2,\r\n ScriptPortProgramRamCost: 0.05,\r\n ScriptRunRamCost: 1.0,\r\n ScriptExecRamCost: 1.3,\r\n ScriptSpawnRamCost: 2.0,\r\n ScriptScpRamCost: 0.6,\r\n ScriptKillRamCost: 0.5,\r\n ScriptHasRootAccessRamCost: 0.05,\r\n ScriptGetHostnameRamCost: 0.05,\r\n ScriptGetHackingLevelRamCost: 0.05,\r\n ScriptGetMultipliersRamCost: 4.0,\r\n ScriptGetServerRamCost: 0.1,\r\n ScriptFileExistsRamCost: 0.1,\r\n ScriptIsRunningRamCost: 0.1,\r\n ScriptHacknetNodesRamCost: 4.0,\r\n ScriptHNUpgLevelRamCost: 0.4,\r\n ScriptHNUpgRamRamCost: 0.6,\r\n ScriptHNUpgCoreRamCost: 0.8,\r\n ScriptGetStockRamCost: 2.0,\r\n ScriptBuySellStockRamCost: 2.5,\r\n ScriptGetPurchaseServerRamCost: 0.25,\r\n ScriptPurchaseServerRamCost: 2.25,\r\n ScriptGetPurchasedServerLimit: 0.05,\r\n ScriptGetPurchasedServerMaxRam: 0.05,\r\n ScriptRoundRamCost: 0.05,\r\n ScriptReadWriteRamCost: 1.0,\r\n ScriptArbScriptRamCost: 1.0,\r\n ScriptGetScriptRamCost: 0.1,\r\n ScriptGetHackTimeRamCost: 0.05,\r\n ScriptGetFavorToDonate: 0.10,\r\n ScriptCodingContractBaseRamCost: 10,\r\n ScriptSleeveBaseRamCost: 4,\r\n\r\n ScriptSingularityFn1RamCost: 2,\r\n ScriptSingularityFn2RamCost: 3,\r\n ScriptSingularityFn3RamCost: 5,\r\n\r\n ScriptGangApiBaseRamCost: 4,\r\n\r\n ScriptBladeburnerApiBaseRamCost: 4,\r\n}\r\n\r\nexport const RamCosts: IMap = {\r\n hacknet: {\r\n numNodes: () => 0,\r\n purchaseNode: () => 0,\r\n getPurchaseNodeCost: () => 0,\r\n getNodeStats: () => 0,\r\n upgradeLevel: () => 0,\r\n upgradeRam: () => 0,\r\n upgradeCore: () => 0,\r\n upgradeCache: () => 0,\r\n getLevelUpgradeCost: () => 0,\r\n getRamUpgradeCost: () => 0,\r\n getCoreUpgradeCost: () => 0,\r\n getCacheUpgradeCost: () => 0,\r\n numHashes: () => 0,\r\n hashCost: () => 0,\r\n spendHashes: () => 0,\r\n },\r\n sprintf: () => 0,\r\n vsprintf: () => 0,\r\n scan: () => RamCostConstants.ScriptScanRamCost,\r\n hack: () => RamCostConstants.ScriptHackRamCost,\r\n hackAnalyzeThreads: () => RamCostConstants.ScriptHackAnalyzeRamCost,\r\n hackAnalyzePercent: () => RamCostConstants.ScriptHackAnalyzeRamCost,\r\n hackChance: () => RamCostConstants.ScriptHackAnalyzeRamCost,\r\n sleep: () => 0,\r\n grow: () => RamCostConstants.ScriptGrowRamCost,\r\n growthAnalyze: () => RamCostConstants.ScriptGrowthAnalyzeRamCost,\r\n weaken: () => RamCostConstants.ScriptWeakenRamCost,\r\n print: () => 0,\r\n tprint: () => 0,\r\n clearLog: () => 0,\r\n disableLog: () => 0,\r\n enableLog: () => 0,\r\n isLogEnabled: () => 0,\r\n getScriptLogs: () => 0,\r\n nuke: () => RamCostConstants.ScriptPortProgramRamCost,\r\n brutessh: () => RamCostConstants.ScriptPortProgramRamCost,\r\n ftpcrack: () => RamCostConstants.ScriptPortProgramRamCost,\r\n relaysmtp: () => RamCostConstants.ScriptPortProgramRamCost,\r\n httpworm: () => RamCostConstants.ScriptPortProgramRamCost,\r\n sqlinject: () => RamCostConstants.ScriptPortProgramRamCost,\r\n run: () => RamCostConstants.ScriptRunRamCost,\r\n exec: () => RamCostConstants.ScriptExecRamCost,\r\n spawn: () => RamCostConstants.ScriptSpawnRamCost,\r\n kill: () => RamCostConstants.ScriptKillRamCost,\r\n killall: () => RamCostConstants.ScriptKillRamCost,\r\n exit: () => 0,\r\n scp: () => RamCostConstants.ScriptScpRamCost,\r\n ls: () => RamCostConstants.ScriptScanRamCost,\r\n ps: () => RamCostConstants.ScriptScanRamCost,\r\n hasRootAccess: () => RamCostConstants.ScriptHasRootAccessRamCost,\r\n getIp: () => RamCostConstants.ScriptGetHostnameRamCost,\r\n getHostname: () => RamCostConstants.ScriptGetHostnameRamCost,\r\n getHackingLevel: () => RamCostConstants.ScriptGetHackingLevelRamCost,\r\n getHackingMultipliers: () => RamCostConstants.ScriptGetMultipliersRamCost,\r\n getHacknetMultipliers: () => RamCostConstants.ScriptGetMultipliersRamCost,\r\n getBitNodeMultipliers: () => RamCostConstants.ScriptGetMultipliersRamCost,\r\n getServerMoneyAvailable: () => RamCostConstants.ScriptGetServerRamCost,\r\n getServerSecurityLevel: () => RamCostConstants.ScriptGetServerRamCost,\r\n getServerBaseSecurityLevel: () => RamCostConstants.ScriptGetServerRamCost,\r\n getServerMinSecurityLevel: () => RamCostConstants.ScriptGetServerRamCost,\r\n getServerRequiredHackingLevel: () => RamCostConstants.ScriptGetServerRamCost,\r\n getServerMaxMoney: () => RamCostConstants.ScriptGetServerRamCost,\r\n getServerGrowth: () => RamCostConstants.ScriptGetServerRamCost,\r\n getServerNumPortsRequired: () => RamCostConstants.ScriptGetServerRamCost,\r\n getServerRam: () => RamCostConstants.ScriptGetServerRamCost,\r\n serverExists: () => RamCostConstants.ScriptGetServerRamCost,\r\n fileExists: () => RamCostConstants.ScriptFileExistsRamCost,\r\n isRunning: () => RamCostConstants.ScriptIsRunningRamCost,\r\n getStockSymbols: () => RamCostConstants.ScriptGetStockRamCost,\r\n getStockPrice: () => RamCostConstants.ScriptGetStockRamCost,\r\n getStockAskPrice: () => RamCostConstants.ScriptGetStockRamCost,\r\n getStockBidPrice: () => RamCostConstants.ScriptGetStockRamCost,\r\n getStockPosition: () => RamCostConstants.ScriptGetStockRamCost,\r\n getStockMaxShares: () => RamCostConstants.ScriptGetStockRamCost,\r\n getStockPurchaseCost: () => RamCostConstants.ScriptGetStockRamCost,\r\n getStockSaleGain: () => RamCostConstants.ScriptGetStockRamCost,\r\n buyStock: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n sellStock: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n shortStock: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n sellShort: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n placeOrder: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n cancelOrder: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n getOrders: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n getStockVolatility: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n getStockForecast: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n purchase4SMarketData: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n purchase4SMarketDataTixApi: () => RamCostConstants.ScriptBuySellStockRamCost,\r\n getPurchasedServerLimit: () => RamCostConstants.ScriptGetPurchasedServerLimit,\r\n getPurchasedServerMaxRam: () => RamCostConstants.ScriptGetPurchasedServerMaxRam,\r\n getPurchasedServerCost: () => RamCostConstants.ScriptGetPurchaseServerRamCost,\r\n purchaseServer: () => RamCostConstants.ScriptPurchaseServerRamCost,\r\n deleteServer: () => RamCostConstants.ScriptPurchaseServerRamCost,\r\n getPurchasedServers: () => RamCostConstants.ScriptPurchaseServerRamCost,\r\n write: () => RamCostConstants.ScriptReadWriteRamCost,\r\n tryWrite: () => RamCostConstants.ScriptReadWriteRamCost,\r\n read: () => RamCostConstants.ScriptReadWriteRamCost,\r\n peek: () => RamCostConstants.ScriptReadWriteRamCost,\r\n clear: () => RamCostConstants.ScriptReadWriteRamCost,\r\n getPortHandle: () => RamCostConstants.ScriptReadWriteRamCost * 10,\r\n rm: () => RamCostConstants.ScriptReadWriteRamCost,\r\n scriptRunning: () => RamCostConstants.ScriptArbScriptRamCost,\r\n scriptKill: () => RamCostConstants.ScriptArbScriptRamCost,\r\n getScriptName: () => 0,\r\n getScriptRam: () => RamCostConstants.ScriptGetScriptRamCost,\r\n getHackTime: () => RamCostConstants.ScriptGetHackTimeRamCost,\r\n getGrowTime: () => RamCostConstants.ScriptGetHackTimeRamCost,\r\n getWeakenTime: () => RamCostConstants.ScriptGetHackTimeRamCost,\r\n getScriptIncome: () => RamCostConstants.ScriptGetScriptRamCost,\r\n getScriptExpGain: () => RamCostConstants.ScriptGetScriptRamCost,\r\n nFormat: () => 0,\r\n getTimeSinceLastAug: () => RamCostConstants.ScriptGetHackTimeRamCost,\r\n prompt: () => 0,\r\n wget: () => 0,\r\n getFavorToDonate: () => RamCostConstants.ScriptGetFavorToDonate,\r\n\r\n // Singularity Functions\r\n universityCourse: () => RamCostConstants.ScriptSingularityFn1RamCost,\r\n gymWorkout: () => RamCostConstants.ScriptSingularityFn1RamCost,\r\n travelToCity: () => RamCostConstants.ScriptSingularityFn1RamCost,\r\n purchaseTor: () => RamCostConstants.ScriptSingularityFn1RamCost,\r\n purchaseProgram: () => RamCostConstants.ScriptSingularityFn1RamCost,\r\n getStats: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,\r\n getCharacterInformation: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,\r\n isBusy: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,\r\n stopAction: () => RamCostConstants.ScriptSingularityFn1RamCost / 2,\r\n upgradeHomeRam: () => RamCostConstants.ScriptSingularityFn2RamCost,\r\n getUpgradeHomeRamCost: () => RamCostConstants.ScriptSingularityFn2RamCost / 2,\r\n workForCompany: () => RamCostConstants.ScriptSingularityFn2RamCost,\r\n applyToCompany: () => RamCostConstants.ScriptSingularityFn2RamCost,\r\n getCompanyRep: () => RamCostConstants.ScriptSingularityFn2RamCost / 3,\r\n getCompanyFavor: () => RamCostConstants.ScriptSingularityFn2RamCost / 3,\r\n getCompanyFavorGain: () => RamCostConstants.ScriptSingularityFn2RamCost / 4,\r\n checkFactionInvitations: () => RamCostConstants.ScriptSingularityFn2RamCost,\r\n joinFaction: () => RamCostConstants.ScriptSingularityFn2RamCost,\r\n workForFaction: () => RamCostConstants.ScriptSingularityFn2RamCost,\r\n getFactionRep: () => RamCostConstants.ScriptSingularityFn2RamCost / 3,\r\n getFactionFavor: () => RamCostConstants.ScriptSingularityFn2RamCost / 3,\r\n getFactionFavorGain: () => RamCostConstants.ScriptSingularityFn2RamCost / 4,\r\n donateToFaction: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n createProgram: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n commitCrime: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n getCrimeChance: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n getOwnedAugmentations: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n getOwnedSourceFiles: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n getAugmentationsFromFaction: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n getAugmentationPrereq: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n getAugmentationCost: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n purchaseAugmentation: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n installAugmentations: () => RamCostConstants.ScriptSingularityFn3RamCost,\r\n\r\n // Gang API\r\n gang : {\r\n getMemberNames: () => RamCostConstants.ScriptGangApiBaseRamCost / 4,\r\n getGangInformation: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,\r\n getOtherGangInformation: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,\r\n getMemberInformation: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,\r\n canRecruitMember: () => RamCostConstants.ScriptGangApiBaseRamCost / 4,\r\n recruitMember: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,\r\n getTaskNames: () => RamCostConstants.ScriptGangApiBaseRamCost / 4,\r\n setMemberTask: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,\r\n getEquipmentNames: () => RamCostConstants.ScriptGangApiBaseRamCost / 4,\r\n getEquipmentCost: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,\r\n getEquipmentType: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,\r\n purchaseEquipment: () => RamCostConstants.ScriptGangApiBaseRamCost,\r\n ascendMember: () => RamCostConstants.ScriptGangApiBaseRamCost,\r\n setTerritoryWarfare: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,\r\n getChanceToWinClash: () => RamCostConstants.ScriptGangApiBaseRamCost,\r\n getBonusTime: () => 0,\r\n },\r\n\r\n // Bladeburner API\r\n bladeburner : {\r\n getContractNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,\r\n getOperationNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,\r\n getBlackOpNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,\r\n getBlackOpRank: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 2,\r\n getGeneralActionNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,\r\n getSkillNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,\r\n startAction: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n stopBladeburnerAction: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 2,\r\n getCurrentAction: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 4,\r\n getActionTime: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getActionEstimatedSuccessChance: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getActionRepGain: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getActionCountRemaining: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getActionMaxLevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getActionCurrentLevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getActionAutolevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n setActionAutolevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n setActionLevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getRank: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getSkillPoints: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getSkillLevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getSkillUpgradeCost: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n upgradeSkill: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getTeamSize: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n setTeamSize: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getCityEstimatedPopulation: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getCityEstimatedCommunities: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getCityChaos: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getCity: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n switchCity: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getStamina: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n joinBladeburnerFaction: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n joinBladeburnerDivision: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n getBonusTime: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,\r\n },\r\n\r\n // Coding Contract API\r\n codingcontract : {\r\n attempt: () => RamCostConstants.ScriptCodingContractBaseRamCost,\r\n getContractType: () => RamCostConstants.ScriptCodingContractBaseRamCost / 2,\r\n getData: () => RamCostConstants.ScriptCodingContractBaseRamCost / 2,\r\n getDescription: () => RamCostConstants.ScriptCodingContractBaseRamCost / 2,\r\n getNumTriesRemaining: () => RamCostConstants.ScriptCodingContractBaseRamCost / 2,\r\n },\r\n\r\n // Duplicate Sleeve API\r\n sleeve : {\r\n getNumSleeves: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n setToShockRecovery: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n setToSynchronize: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n setToCommitCrime: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n setToUniversityCourse: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n travel: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n setToCompanyWork: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n setToFactionWork: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n setToGymWorkout: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n getSleeveStats: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n getTask: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n getInformation: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n getSleeveAugmentations: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n getSleevePurchasableAugs: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n purchaseSleeveAug: () => RamCostConstants.ScriptSleeveBaseRamCost,\r\n },\r\n\r\n heart: {\r\n // Easter egg function\r\n break : () => 0,\r\n }\r\n}\r\n\r\nexport function getRamCost(...args: string[]): number {\r\n if (args.length === 0) {\r\n console.warn(`No arguments passed to getRamCost()`);\r\n return 0;\r\n }\r\n\r\n let curr = RamCosts[args[0]];\r\n for (let i = 1; i < args.length; ++i) {\r\n if (curr == null) {\r\n console.warn(`Invalid function passed to getRamCost: ${args}`);\r\n return 0;\r\n }\r\n\r\n const currType = typeof curr;\r\n if (currType === \"function\" || currType === \"number\") {\r\n break;\r\n }\r\n\r\n curr = curr[args[i]];\r\n }\r\n\r\n const currType = typeof curr;\r\n if (currType === \"function\") {\r\n return curr();\r\n }\r\n\r\n if (currType === \"number\") {\r\n return curr;\r\n }\r\n\r\n console.warn(`Expected type: ${currType}`);\r\n return 0;\r\n}\r\n","/**\r\n * Gets a random integer bounded by the values passed in.\r\n * @param min The minimum value in the range.\r\n * @param max The maximum value in the range.\r\n */\r\nexport function getRandomInt(min: number, max: number) {\r\n const lower: number = Math.min(min, max);\r\n const upper: number = Math.max(min, max);\r\n\r\n return Math.floor(Math.random() * (upper - lower + 1)) + lower;\r\n}\r\n","/* Generic Reviver, toJSON, and fromJSON functions used for saving and loading objects */\r\n\r\n// A generic \"smart reviver\" function.\r\n// Looks for object values with a `ctor` property and\r\n// a `data` property. If it finds them, and finds a matching\r\n// constructor that has a `fromJSON` property on it, it hands\r\n// off to that `fromJSON` fuunction, passing in the value.\r\nfunction Reviver(key, value) {\r\n\tvar ctor;\r\n if (value == null) {\r\n console.log(\"Reviver WRONGLY called with key: \" + key + \", and value: \" + value);\r\n return 0;\r\n }\r\n\r\n\tif (typeof value === \"object\" &&\r\n\t\ttypeof value.ctor === \"string\" &&\r\n\t\ttypeof value.data !== \"undefined\") {\r\n\t\t\t// Compatibility for version v0.43.1\r\n\t\t\t// TODO Remove this eventually\r\n\t\t\tif (value.ctor === \"AllServersMap\") {\r\n\t\t\t\tconsole.log('Converting AllServersMap for v0.43.1');\r\n\t\t\t\treturn value.data;\r\n\t\t\t}\r\n\r\n\t\t\tctor = Reviver.constructors[value.ctor] || window[value.ctor];\r\n\r\n\t\t\tif (typeof ctor === \"function\" &&\r\n\t\t\t\ttypeof ctor.fromJSON === \"function\") {\r\n\r\n\t\t\t\t\treturn ctor.fromJSON(value);\r\n\t\t\t}\r\n\t}\r\n\treturn value;\r\n}\r\nReviver.constructors = {}; // A list of constructors the smart reviver should know about\r\n\r\n// A generic \"toJSON\" function that creates the data expected\r\n// by Reviver.\r\n// `ctorName` The name of the constructor to use to revive it\r\n// `obj` The object being serialized\r\n// `keys` (Optional) Array of the properties to serialize,\r\n// if not given then all of the objects \"own\" properties\r\n// that don't have function values will be serialized.\r\n// (Note: If you list a property in `keys`, it will be serialized\r\n// regardless of whether it's an \"own\" property.)\r\n// Returns: The structure (which will then be turned into a string\r\n// as part of the JSON.stringify algorithm)\r\nfunction Generic_toJSON(ctorName, obj, keys) {\r\n var data, index, key;\r\n\r\n if (!keys) {\r\n keys = Object.keys(obj); // Only \"own\" properties are included\r\n }\r\n\r\n data = {};\r\n for (let index = 0; index < keys.length; ++index) {\r\n key = keys[index];\r\n data[key] = obj[key];\r\n }\r\n return {ctor: ctorName, data: data};\r\n}\r\n\r\n// A generic \"fromJSON\" function for use with Reviver: Just calls the\r\n// constructor function with no arguments, then applies all of the\r\n// key/value pairs from the raw data to the instance. Only useful for\r\n// constructors that can be reasonably called without arguments!\r\n// `ctor` The constructor to call\r\n// `data` The data to apply\r\n// Returns: The object\r\nfunction Generic_fromJSON(ctor, data) {\r\n var obj, name;\r\n\r\n obj = new ctor();\r\n for (name in data) {\r\n obj[name] = data[name];\r\n }\r\n return obj;\r\n}\r\n\r\nexport {Reviver, Generic_toJSON, Generic_fromJSON};\r\n","import { CONSTANTS } from \"../src/Constants\";\r\nimport { Order } from \"../src/StockMarket/Order\";\r\n//import { processOrders } from \"../src/StockMarket/OrderProcessing\";\r\nimport { Stock } from \"../src/StockMarket/Stock\";\r\n/*\r\nimport {\r\n deleteStockMarket,\r\n initStockMarket,\r\n initSymbolToStockMap,\r\n loadStockMarket,\r\n StockMarket,\r\n SymbolToStockMap,\r\n} from \"../src/StockMarket/StockMarket\";\r\n*/\r\nimport {\r\n calculateIncreasingPriceMovement,\r\n calculateDecreasingPriceMovement,\r\n forecastChangePerPriceMovement,\r\n getBuyTransactionCost,\r\n getSellTransactionGain,\r\n processBuyTransactionPriceMovement,\r\n processSellTransactionPriceMovement,\r\n} from \"../src/StockMarket/StockMarketHelpers\";\r\nimport { OrderTypes } from \"../src/StockMarket/data/OrderTypes\"\r\nimport { PositionTypes } from \"../src/StockMarket/data/PositionTypes\";\r\n\r\nconst assert = chai.assert;\r\nconst expect = chai.expect;\r\n\r\nconsole.log(\"Beginning Stock Market Tests\");\r\n\r\ndescribe(\"Stock Market Tests\", function() {\r\n const commission = CONSTANTS.StockMarketCommission;\r\n\r\n // Generic Stock object that can be used by each test\r\n let stock;\r\n const ctorParams = {\r\n b: true,\r\n initPrice: 10e3,\r\n marketCap: 5e9,\r\n mv: 1,\r\n name: \"MockStock\",\r\n otlkMag: 10,\r\n spreadPerc: 1,\r\n shareTxForMovement: 5e3,\r\n symbol: \"mock\",\r\n };\r\n\r\n beforeEach(function() {\r\n function construct() {\r\n stock = new Stock(ctorParams);\r\n }\r\n\r\n expect(construct).to.not.throw();\r\n });\r\n\r\n describe(\"Stock Class\", function() {\r\n describe(\"constructor\", function() {\r\n it(\"should have default parameters\", function() {\r\n let defaultStock;\r\n function construct() {\r\n defaultStock = new Stock();\r\n }\r\n\r\n expect(construct).to.not.throw();\r\n expect(defaultStock.name).to.equal(\"\");\r\n });\r\n\r\n it(\"should properly initialize props from parameters\", function() {\r\n expect(stock.name).to.equal(ctorParams.name);\r\n expect(stock.symbol).to.equal(ctorParams.symbol);\r\n expect(stock.price).to.equal(ctorParams.initPrice);\r\n expect(stock.lastPrice).to.equal(ctorParams.initPrice);\r\n expect(stock.b).to.equal(ctorParams.b);\r\n expect(stock.mv).to.equal(ctorParams.mv);\r\n expect(stock.shareTxForMovement).to.equal(ctorParams.shareTxForMovement);\r\n expect(stock.shareTxUntilMovement).to.equal(ctorParams.shareTxForMovement);\r\n expect(stock.maxShares).to.be.below(stock.totalShares);\r\n expect(stock.spreadPerc).to.equal(ctorParams.spreadPerc);\r\n expect(stock.priceMovementPerc).to.be.a(\"number\");\r\n expect(stock.priceMovementPerc).to.be.at.most(stock.spreadPerc);\r\n expect(stock.priceMovementPerc).to.be.at.least(0);\r\n });\r\n\r\n it (\"should properly initialize props from range-values\", function() {\r\n let stock;\r\n const params = {\r\n b: true,\r\n initPrice: {\r\n max: 10e3,\r\n min: 1e3,\r\n },\r\n marketCap: 5e9,\r\n mv: {\r\n divisor: 100,\r\n max: 150,\r\n min: 50,\r\n },\r\n name: \"MockStock\",\r\n otlkMag: 10,\r\n spreadPerc: {\r\n divisor: 10,\r\n max: 10,\r\n min: 1,\r\n },\r\n shareTxForMovement: {\r\n max: 10e3,\r\n min: 5e3,\r\n },\r\n symbol: \"mock\",\r\n };\r\n\r\n function construct() {\r\n stock = new Stock(params);\r\n }\r\n\r\n expect(construct).to.not.throw();\r\n expect(stock.price).to.be.within(params.initPrice.min, params.initPrice.max);\r\n expect(stock.mv).to.be.within(params.mv.min / params.mv.divisor, params.mv.max / params.mv.divisor);\r\n expect(stock.spreadPerc).to.be.within(params.spreadPerc.min / params.spreadPerc.divisor, params.spreadPerc.max / params.spreadPerc.divisor);\r\n expect(stock.shareTxForMovement).to.be.within(params.shareTxForMovement.min, params.shareTxForMovement.max);\r\n });\r\n\r\n it(\"should round the 'totalShare' prop to the nearest 100k\", function() {\r\n expect(stock.totalShares % 100e3).to.equal(0);\r\n });\r\n });\r\n\r\n describe(\"#changePrice()\", function() {\r\n it(\"should set both the last price and current price properties\", function() {\r\n const newPrice = 20e3;\r\n stock.changePrice(newPrice);\r\n expect(stock.lastPrice).to.equal(ctorParams.initPrice);\r\n expect(stock.price).to.equal(newPrice);\r\n });\r\n });\r\n\r\n describe(\"#getAskPrice()\", function() {\r\n it(\"should return the price increased by spread percentage\", function() {\r\n const perc = stock.spreadPerc / 100;\r\n expect(perc).to.be.at.most(1);\r\n expect(perc).to.be.at.least(0);\r\n\r\n const expected = stock.price * (1 + perc);\r\n expect(stock.getAskPrice()).to.equal(expected);\r\n });\r\n });\r\n\r\n describe(\"#getBidPrice()\", function() {\r\n it(\"should return the price decreased by spread percentage\", function() {\r\n const perc = stock.spreadPerc / 100;\r\n expect(perc).to.be.at.most(1);\r\n expect(perc).to.be.at.least(0);\r\n\r\n const expected = stock.price * (1 - perc);\r\n expect(stock.getBidPrice()).to.equal(expected);\r\n });\r\n });\r\n });\r\n\r\n /*\r\n // TODO These tests fail due to circular dependency errors\r\n describe(\"StockMarket object\", function() {\r\n describe(\"Initialization\", function() {\r\n // Keeps track of initialized stocks. Contains their symbols\r\n const stocks = [];\r\n\r\n before(function() {\r\n expect(initStockMarket).to.not.throw();\r\n expect(initSymbolToStockMap).to.not.throw();\r\n });\r\n\r\n it(\"should have Stock objects\", function() {\r\n for (const prop in StockMarket) {\r\n const stock = StockMarket[prop];\r\n if (stock instanceof Stock) {\r\n stocks.push(stock.symbol);\r\n }\r\n }\r\n\r\n // We'll just check that there are some stocks\r\n expect(stocks.length).to.be.at.least(1);\r\n });\r\n\r\n it(\"should have an order book in the 'Orders' property\", function() {\r\n expect(StockMarket).to.have.property(\"Orders\");\r\n\r\n const orderbook = StockMarket[\"Orders\"];\r\n for (const symbol of stocks) {\r\n const ordersForStock = orderbook[symbol];\r\n expect(ordersForStock).to.be.an(\"array\");\r\n expect(ordersForStock.length).to.equal(0);\r\n }\r\n });\r\n\r\n it(\"should have properties for managing game cycles\", function() {\r\n expect(StockMarket).to.have.property(\"storedCycles\");\r\n expect(StockMarket).to.have.property(\"lastUpdate\");\r\n });\r\n });\r\n\r\n // Because 'StockMarket' is a global object, the effects of initialization from\r\n // the block above should still stand\r\n describe(\"Deletion\", function() {\r\n it(\"should set StockMarket to be an empty object\", function() {\r\n expect(StockMarket).to.be.an(\"object\").that.is.not.empty;\r\n deleteStockMarket();\r\n expect(StockMarket).to.be.an(\"object\").that.is.empty;\r\n });\r\n });\r\n\r\n // Reset stock market for each test\r\n beforeEach(function() {\r\n deleteStockMarket();\r\n initStockMarket();\r\n initSymbolToStockMap();\r\n });\r\n\r\n it(\"should properly initialize\", function() {\r\n\r\n });\r\n });\r\n */\r\n\r\n describe(\"Transaction Cost Calculator Functions\", function() {\r\n describe(\"getBuyTransactionCost()\", function() {\r\n it(\"should fail on invalid 'stock' argument\", function() {\r\n const res = getBuyTransactionCost({}, 10, PositionTypes.Long);\r\n expect(res).to.equal(null);\r\n });\r\n\r\n it(\"should fail on invalid 'shares' arg\", function() {\r\n let res = getBuyTransactionCost(stock, NaN, PositionTypes.Long);\r\n expect(res).to.equal(null);\r\n\r\n res = getBuyTransactionCost(stock, -1, PositionTypes.Long);\r\n expect(res).to.equal(null);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that doesn't trigger a price movement\", function() {\r\n const shares = ctorParams.shareTxForMovement / 2;\r\n const res = getBuyTransactionCost(stock, shares, PositionTypes.Long);\r\n expect(res).to.equal(shares * stock.getAskPrice() + commission);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that doesn't trigger a price movement\", function() {\r\n const shares = ctorParams.shareTxForMovement / 2;\r\n const res = getBuyTransactionCost(stock, shares, PositionTypes.Short);\r\n expect(res).to.equal(shares * stock.getBidPrice() + commission);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that trigger price movements\", function() {\r\n const sharesPerMvmt = ctorParams.shareTxForMovement;\r\n const shares = sharesPerMvmt * 3;\r\n const res = getBuyTransactionCost(stock, shares, PositionTypes.Long);\r\n\r\n // Calculate expected cost\r\n const secondPrice = stock.getAskPrice() * calculateIncreasingPriceMovement(stock);\r\n const thirdPrice = secondPrice * calculateIncreasingPriceMovement(stock);\r\n let expected = (sharesPerMvmt * stock.getAskPrice()) + (sharesPerMvmt * secondPrice) + (sharesPerMvmt * thirdPrice);\r\n\r\n expect(res).to.equal(expected + commission);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that trigger price movements\", function() {\r\n const sharesPerMvmt = ctorParams.shareTxForMovement;\r\n const shares = sharesPerMvmt * 3;\r\n const res = getBuyTransactionCost(stock, shares, PositionTypes.Short);\r\n\r\n // Calculate expected cost\r\n const secondPrice = stock.getBidPrice() * calculateDecreasingPriceMovement(stock);\r\n const thirdPrice = secondPrice * calculateDecreasingPriceMovement(stock);\r\n let expected = (sharesPerMvmt * stock.getBidPrice()) + (sharesPerMvmt * secondPrice) + (sharesPerMvmt * thirdPrice);\r\n\r\n expect(res).to.equal(expected + commission);\r\n });\r\n\r\n it(\"should cap the 'shares' argument at the stock's maximum number of shares\", function() {\r\n const maxRes = getBuyTransactionCost(stock, stock.maxShares, PositionTypes.Long);\r\n const exceedRes = getBuyTransactionCost(stock, stock.maxShares * 10, PositionTypes.Long);\r\n expect(maxRes).to.equal(exceedRes);\r\n });\r\n });\r\n\r\n describe(\"getSellTransactionGain()\", function() {\r\n it(\"should fail on invalid 'stock' argument\", function() {\r\n const res = getSellTransactionGain({}, 10, PositionTypes.Long);\r\n expect(res).to.equal(null);\r\n });\r\n\r\n it(\"should fail on invalid 'shares' arg\", function() {\r\n let res = getSellTransactionGain(stock, NaN, PositionTypes.Long);\r\n expect(res).to.equal(null);\r\n\r\n res = getSellTransactionGain(stock, -1, PositionTypes.Long);\r\n expect(res).to.equal(null);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that doesn't trigger a price movement\", function() {\r\n const shares = ctorParams.shareTxForMovement / 2;\r\n const res = getSellTransactionGain(stock, shares, PositionTypes.Long);\r\n const expected = shares * stock.getBidPrice() - commission;\r\n expect(res).to.equal(expected);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that doesn't trigger a price movement\", function() {\r\n // We need to set this property in order to calculate gains from short position\r\n stock.playerAvgShortPx = stock.price * 2;\r\n\r\n const shares = ctorParams.shareTxForMovement / 2;\r\n const res = getSellTransactionGain(stock, shares, PositionTypes.Short);\r\n const expected = (shares * stock.playerAvgShortPx) + (shares * (stock.playerAvgShortPx - stock.getAskPrice())) - commission;\r\n expect(res).to.equal(expected);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that trigger price movements\", function() {\r\n const sharesPerMvmt = ctorParams.shareTxForMovement;\r\n const shares = sharesPerMvmt * 3;\r\n const res = getSellTransactionGain(stock, shares, PositionTypes.Long);\r\n\r\n // Calculated expected gain\r\n const mvmt = calculateDecreasingPriceMovement(stock);\r\n const secondPrice = stock.getBidPrice() * mvmt;\r\n const thirdPrice = secondPrice * mvmt;\r\n const expected = (sharesPerMvmt * stock.getBidPrice()) + (sharesPerMvmt * secondPrice) + (sharesPerMvmt * thirdPrice);\r\n\r\n expect(res).to.equal(expected - commission);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that trigger price movements\", function() {\r\n // We need to set this property in order to calculate gains from short position\r\n stock.playerAvgShortPx = stock.price * 2;\r\n\r\n const sharesPerMvmt = ctorParams.shareTxForMovement;\r\n const shares = sharesPerMvmt * 3;\r\n const res = getSellTransactionGain(stock, shares, PositionTypes.Short);\r\n\r\n // Calculate expected gain\r\n const mvmt = calculateIncreasingPriceMovement(stock);\r\n const secondPrice = stock.getAskPrice() * mvmt;\r\n const thirdPrice = secondPrice * mvmt;\r\n function getGainForPrice(thisPrice) {\r\n const origCost = sharesPerMvmt * stock.playerAvgShortPx;\r\n return origCost + ((stock.playerAvgShortPx - thisPrice) * sharesPerMvmt);\r\n }\r\n const expected = getGainForPrice(stock.getAskPrice()) + getGainForPrice(secondPrice) + getGainForPrice(thirdPrice);\r\n\r\n expect(res).to.equal(expected - commission);\r\n });\r\n\r\n it(\"should cap the 'shares' argument at the stock's maximum number of shares\", function() {\r\n const maxRes = getSellTransactionGain(stock, stock.maxShares, PositionTypes.Long);\r\n const exceedRes = getSellTransactionGain(stock, stock.maxShares * 10, PositionTypes.Long);\r\n expect(maxRes).to.equal(exceedRes);\r\n });\r\n });\r\n });\r\n\r\n describe(\"Price Movement Processor Functions\", function() {\r\n // N = 1 is the original price\r\n function getNthPriceIncreasing(origPrice, n) {\r\n let price = origPrice;\r\n for (let i = 1; i < n; ++i) {\r\n price *= calculateIncreasingPriceMovement(stock);\r\n }\r\n\r\n return price;\r\n }\r\n\r\n // N = 1 is the original price\r\n function getNthPriceDecreasing(origPrice, n) {\r\n let price = origPrice;\r\n for (let i = 1; i < n; ++i) {\r\n price *= calculateDecreasingPriceMovement(stock);\r\n }\r\n\r\n return price;\r\n }\r\n\r\n // N = 1 is the original forecast\r\n function getNthForecast(origForecast, n) {\r\n return origForecast - forecastChangePerPriceMovement * (n - 1);\r\n }\r\n\r\n describe(\"processBuyTransactionPriceMovement()\", function() {\r\n const noMvmtShares = Math.round(ctorParams.shareTxForMovement / 2.2);\r\n const mvmtShares = ctorParams.shareTxForMovement * 3 + noMvmtShares;\r\n\r\n it(\"should do nothing on invalid 'stock' argument\", function() {\r\n const oldPrice = stock.price;\r\n const oldTracker = stock.shareTxUntilMovement;\r\n\r\n processBuyTransactionPriceMovement({}, mvmtShares, PositionTypes.Long);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.shareTxUntilMovement).to.equal(oldTracker);\r\n });\r\n\r\n it(\"should do nothing on invalid 'shares' arg\", function() {\r\n const oldPrice = stock.price;\r\n const oldTracker = stock.shareTxUntilMovement;\r\n\r\n processBuyTransactionPriceMovement(stock, NaN, PositionTypes.Long);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.shareTxUntilMovement).to.equal(oldTracker);\r\n\r\n processBuyTransactionPriceMovement(stock, -1, PositionTypes.Long);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.shareTxUntilMovement).to.equal(oldTracker);\r\n });\r\n\r\n it(\"should properly evaluate a LONG transaction that doesn't trigger a price movement\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Long);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.otlkMag).to.equal(oldForecast);\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);\r\n });\r\n\r\n it(\"should properly evaluate a SHORT transaction that doesn't trigger a price movement\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Short);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.otlkMag).to.equal(oldForecast);\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that trigger price movements\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, mvmtShares, PositionTypes.Long);\r\n expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that trigger price movements\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, mvmtShares, PositionTypes.Short);\r\n expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions of exactly 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Long);\r\n expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that total to 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Long);\r\n processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Long);\r\n expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that are a multiple of 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Long);\r\n expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions of exactly 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Short);\r\n expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that total to 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Short);\r\n processBuyTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Short);\r\n expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that are a multiple of 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processBuyTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Short);\r\n expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n });\r\n\r\n describe(\"processSellTransactionPriceMovement()\", function() {\r\n const noMvmtShares = Math.round(ctorParams.shareTxForMovement / 2.2);\r\n const mvmtShares = ctorParams.shareTxForMovement * 3 + noMvmtShares;\r\n\r\n it(\"should do nothing on invalid 'stock' argument\", function() {\r\n const oldPrice = stock.price;\r\n const oldTracker = stock.shareTxUntilMovement;\r\n\r\n processSellTransactionPriceMovement({}, mvmtShares, PositionTypes.Long);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.shareTxUntilMovement).to.equal(oldTracker);\r\n });\r\n\r\n it(\"should do nothing on invalid 'shares' arg\", function() {\r\n const oldPrice = stock.price;\r\n const oldTracker = stock.shareTxUntilMovement;\r\n\r\n processSellTransactionPriceMovement(stock, NaN, PositionTypes.Long);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.shareTxUntilMovement).to.equal(oldTracker);\r\n\r\n processSellTransactionPriceMovement(stock, -1, PositionTypes.Long);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.shareTxUntilMovement).to.equal(oldTracker);\r\n });\r\n\r\n it(\"should properly evaluate a LONG transaction that doesn't trigger a price movement\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Long);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.otlkMag).to.equal(oldForecast);\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);\r\n });\r\n\r\n it(\"should properly evaluate a SHORT transaction that doesn't trigger a price movement\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, noMvmtShares, PositionTypes.Short);\r\n expect(stock.price).to.equal(oldPrice);\r\n expect(stock.otlkMag).to.equal(oldForecast);\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that trigger price movements\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, mvmtShares, PositionTypes.Long);\r\n expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that trigger price movements\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, mvmtShares, PositionTypes.Short);\r\n expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement - noMvmtShares);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions of exactly 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Long);\r\n expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that total to 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Long);\r\n processSellTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Long);\r\n expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 2));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate LONG transactions that are a multiple of 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Long);\r\n expect(stock.price).to.equal(getNthPriceDecreasing(oldPrice, 4));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions of exactly 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, stock.shareTxForMovement, PositionTypes.Short);\r\n expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that total to 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, Math.round(stock.shareTxForMovement / 2), PositionTypes.Short);\r\n processSellTransactionPriceMovement(stock, stock.shareTxUntilMovement, PositionTypes.Short);\r\n expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 2));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 2));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n\r\n it(\"should properly evaluate SHORT transactions that are a multiple of 'shareTxForMovement' shares\", function() {\r\n const oldPrice = stock.price;\r\n const oldForecast = stock.otlkMag;\r\n\r\n processSellTransactionPriceMovement(stock, 3 * stock.shareTxForMovement, PositionTypes.Short);\r\n expect(stock.price).to.equal(getNthPriceIncreasing(oldPrice, 4));\r\n expect(stock.otlkMag).to.equal(getNthForecast(oldForecast, 4));\r\n expect(stock.shareTxUntilMovement).to.equal(stock.shareTxForMovement);\r\n });\r\n });\r\n });\r\n\r\n describe(\"Order Class\", function() {\r\n it(\"should throw on invalid arguments\", function() {\r\n function invalid1() {\r\n return new Order({}, 1, 1, OrderTypes.LimitBuy, PositionTypes.Long);\r\n }\r\n function invalid2() {\r\n return new Order(\"FOO\", \"z\", 0, OrderTypes.LimitBuy, PositionTypes.Short);\r\n }\r\n function invalid3() {\r\n return new Order(\"FOO\", 1, {}, OrderTypes.LimitBuy, PositionTypes.Short);\r\n }\r\n function invalid4() {\r\n return new Order(\"FOO\", 1, NaN, OrderTypes.LimitBuy, PositionTypes.Short);\r\n }\r\n function invalid5() {\r\n return new Order(\"FOO\", NaN, 0, OrderTypes.LimitBuy, PositionTypes.Short);\r\n }\r\n\r\n expect(invalid1).to.throw();\r\n expect(invalid2).to.throw();\r\n expect(invalid3).to.throw();\r\n expect(invalid4).to.throw();\r\n expect(invalid5).to.throw();\r\n });\r\n });\r\n\r\n describe(\"Order Processing\", function() {\r\n\r\n });\r\n});\r\n","/**\r\n * TODO This should also test the calcualteRamUsage() function from\r\n * /Script/RamCalculations but there's some issues with getting tests to run\r\n * when any npm package is included in the build (/Script/RamCalculations includes\r\n * walk from acorn).\r\n */\r\nimport { getRamCost } from \"../../src/Netscript/RamCostGenerator\";\r\n//import { calculateRamUsage } from \"../../src/Script/RamCalculations\"\r\n\r\nconst assert = chai.assert;\r\nconst expect = chai.expect;\r\n\r\nconsole.log(\"Beginning Netscript Static RAM Calculation/Generation Tests\");\r\n\r\ndescribe(\"Netscript Static RAM Calculation/Generation Tests\", function() {\r\n it(\"should run\", function() {\r\n expect(1).to.equal(1);\r\n });\r\n});\r\n","export enum PositionTypes {\r\n Long = \"L\",\r\n Short = \"S\"\r\n}\r\n","import { Stock } from \"./Stock\";\r\nimport { PositionTypes } from \"./data/PositionTypes\";\r\nimport { CONSTANTS } from \"../Constants\";\r\n\r\n// Amount by which a stock's forecast changes during each price movement\r\nexport const forecastChangePerPriceMovement = 0.1;\r\n\r\n/**\r\n * Given a stock, calculates the amount by which the stock price is multiplied\r\n * for an 'upward' price movement. This does not actually increase the stock's price,\r\n * just calculates the multiplier\r\n * @param {Stock} stock - Stock for price movement\r\n * @returns {number | null} Number by which stock's price should be multiplied. Null for invalid args\r\n */\r\nexport function calculateIncreasingPriceMovement(stock: Stock): number | null {\r\n if (!(stock instanceof Stock)) { return null; }\r\n\r\n return (1 + (stock.priceMovementPerc / 100));\r\n}\r\n\r\n/**\r\n * Given a stock, calculates the amount by which the stock price is multiplied\r\n * for a \"downward\" price movement. This does not actually increase the stock's price,\r\n * just calculates the multiplier\r\n * @param {Stock} stock - Stock for price movement\r\n * @returns {number | null} Number by which stock's price should be multiplied. Null for invalid args\r\n */\r\nexport function calculateDecreasingPriceMovement(stock: Stock): number | null {\r\n if (!(stock instanceof Stock)) { return null; }\r\n\r\n return (1 - (stock.priceMovementPerc / 100));\r\n}\r\n\r\n\r\n/**\r\n * Calculate the total cost of a \"buy\" transaction. This accounts for spread,\r\n * price movements, and commission.\r\n * @param {Stock} stock - Stock being purchased\r\n * @param {number} shares - Number of shares being transacted\r\n * @param {PositionTypes} posType - Long or short position\r\n * @returns {number | null} Total transaction cost. Returns null for an invalid transaction\r\n */\r\nexport function getBuyTransactionCost(stock: Stock, shares: number, posType: PositionTypes): number | null {\r\n if (isNaN(shares) || shares <= 0 || !(stock instanceof Stock)) { return null; }\r\n\r\n // Cap the 'shares' arg at the stock's maximum shares. This'll prevent\r\n // hanging in the case when a really big number is passed in\r\n shares = Math.min(shares, stock.maxShares);\r\n\r\n const isLong = (posType === PositionTypes.Long);\r\n\r\n // If the number of shares doesn't trigger a price movement, its a simple calculation\r\n if (shares <= stock.shareTxUntilMovement) {\r\n if (isLong) {\r\n return (shares * stock.getAskPrice()) + CONSTANTS.StockMarketCommission;\r\n } else {\r\n return (shares * stock.getBidPrice()) + CONSTANTS.StockMarketCommission;\r\n }\r\n }\r\n\r\n // Calculate how many iterations of price changes we need to account for\r\n let remainingShares = shares - stock.shareTxUntilMovement;\r\n let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);\r\n\r\n // The initial cost calculation takes care of the first \"iteration\"\r\n let currPrice = isLong ? stock.getAskPrice() : stock.getBidPrice();\r\n let totalCost = (stock.shareTxUntilMovement * currPrice);\r\n\r\n const increasingMvmt = calculateIncreasingPriceMovement(stock)!;\r\n const decreasingMvmt = calculateDecreasingPriceMovement(stock)!;\r\n\r\n function processPriceMovement() {\r\n if (isLong) {\r\n currPrice *= increasingMvmt;\r\n } else {\r\n currPrice *= decreasingMvmt;\r\n }\r\n }\r\n\r\n for (let i = 1; i < numIterations; ++i) {\r\n processPriceMovement();\r\n\r\n const amt = Math.min(stock.shareTxForMovement, remainingShares);\r\n totalCost += (amt * currPrice);\r\n remainingShares -= amt;\r\n }\r\n\r\n return totalCost + CONSTANTS.StockMarketCommission;\r\n}\r\n\r\n/**\r\n * Processes a buy transaction's resulting price AND forecast movement.\r\n * @param {Stock} stock - Stock being purchased\r\n * @param {number} shares - Number of shares being transacted\r\n * @param {PositionTypes} posType - Long or short position\r\n */\r\nexport function processBuyTransactionPriceMovement(stock: Stock, shares: number, posType: PositionTypes): void {\r\n if (isNaN(shares) || shares <= 0 || !(stock instanceof Stock)) { return; }\r\n\r\n // Cap the 'shares' arg at the stock's maximum shares. This'll prevent\r\n // hanging in the case when a really big number is passed in\r\n shares = Math.min(shares, stock.maxShares);\r\n\r\n const isLong = (posType === PositionTypes.Long);\r\n\r\n let currPrice = stock.price;\r\n function processPriceMovement() {\r\n if (isLong) {\r\n currPrice *= calculateIncreasingPriceMovement(stock)!;\r\n } else {\r\n currPrice *= calculateDecreasingPriceMovement(stock)!;\r\n }\r\n }\r\n\r\n // No price/forecast movement\r\n if (shares <= stock.shareTxUntilMovement) {\r\n stock.shareTxUntilMovement -= shares;\r\n if (stock.shareTxUntilMovement <= 0) {\r\n stock.shareTxUntilMovement = stock.shareTxForMovement;\r\n processPriceMovement();\r\n stock.changePrice(currPrice);\r\n stock.otlkMag -= (forecastChangePerPriceMovement);\r\n }\r\n\r\n return;\r\n }\r\n\r\n // Calculate how many iterations of price changes we need to account for\r\n let remainingShares = shares - stock.shareTxUntilMovement;\r\n let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);\r\n\r\n for (let i = 1; i < numIterations; ++i) {\r\n processPriceMovement();\r\n }\r\n\r\n stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);\r\n if (stock.shareTxUntilMovement === stock.shareTxForMovement || stock.shareTxUntilMovement <= 0) {\r\n // The shareTxUntilMovement ended up at 0 at the end of the \"processing\"\r\n ++numIterations;\r\n stock.shareTxUntilMovement = stock.shareTxForMovement;\r\n processPriceMovement();\r\n }\r\n stock.changePrice(currPrice);\r\n\r\n // Forecast always decreases in magnitude\r\n const forecastChange = Math.min(5, forecastChangePerPriceMovement * (numIterations - 1));\r\n stock.otlkMag -= forecastChange;\r\n if (stock.otlkMag < 0) {\r\n stock.b = !stock.b;\r\n stock.otlkMag = Math.abs(stock.otlkMag);\r\n }\r\n}\r\n\r\n/**\r\n * Calculate the TOTAL amount of money gained from a sale (NOT net profit). This accounts\r\n * for spread, price movements, and commission.\r\n * @param {Stock} stock - Stock being sold\r\n * @param {number} shares - Number of sharse being transacted\r\n * @param {PositionTypes} posType - Long or short position\r\n * @returns {number | null} Amount of money gained from transaction. Returns null for an invalid transaction\r\n */\r\nexport function getSellTransactionGain(stock: Stock, shares: number, posType: PositionTypes): number | null {\r\n if (isNaN(shares) || shares <= 0 || !(stock instanceof Stock)) { return null; }\r\n\r\n // Cap the 'shares' arg at the stock's maximum shares. This'll prevent\r\n // hanging in the case when a really big number is passed in\r\n shares = Math.min(shares, stock.maxShares);\r\n\r\n const isLong = (posType === PositionTypes.Long);\r\n\r\n // If the number of shares doesn't trigger a price mvoement, its a simple calculation\r\n if (shares <= stock.shareTxUntilMovement) {\r\n if (isLong) {\r\n return (shares * stock.getBidPrice()) - CONSTANTS.StockMarketCommission;\r\n } else {\r\n // Calculating gains for a short position requires calculating the profit made\r\n const origCost = shares * stock.playerAvgShortPx;\r\n const profit = ((stock.playerAvgShortPx - stock.getAskPrice()) * shares) - CONSTANTS.StockMarketCommission;\r\n\r\n return origCost + profit;\r\n }\r\n }\r\n\r\n // Calculate how many iterations of price changes we need to account for\r\n let remainingShares = shares - stock.shareTxUntilMovement;\r\n let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);\r\n\r\n // Helper function to calculate gain for a single iteration\r\n function calculateGain(thisPrice: number, thisShares: number) {\r\n if (isLong) {\r\n return thisShares * thisPrice;\r\n } else {\r\n const origCost = thisShares * stock.playerAvgShortPx;\r\n const profit = ((stock.playerAvgShortPx - thisPrice) * thisShares);\r\n\r\n return origCost + profit;\r\n }\r\n }\r\n\r\n // The initial cost calculation takes care of the first \"iteration\"\r\n let currPrice = isLong ? stock.getBidPrice() : stock.getAskPrice();\r\n let totalGain = calculateGain(currPrice, stock.shareTxUntilMovement);\r\n for (let i = 1; i < numIterations; ++i) {\r\n // Price movement\r\n if (isLong) {\r\n currPrice *= calculateDecreasingPriceMovement(stock)!;\r\n } else {\r\n currPrice *= calculateIncreasingPriceMovement(stock)!;\r\n }\r\n\r\n const amt = Math.min(stock.shareTxForMovement, remainingShares);\r\n totalGain += calculateGain(currPrice, amt);\r\n remainingShares -= amt;\r\n }\r\n\r\n return totalGain - CONSTANTS.StockMarketCommission;\r\n}\r\n\r\n/**\r\n * Processes a sell transaction's resulting price movement\r\n * @param {Stock} stock - Stock being sold\r\n * @param {number} shares - Number of sharse being transacted\r\n * @param {PositionTypes} posType - Long or short position\r\n */\r\nexport function processSellTransactionPriceMovement(stock: Stock, shares: number, posType: PositionTypes): void {\r\n if (isNaN(shares) || shares <= 0 || !(stock instanceof Stock)) { return; }\r\n\r\n // Cap the 'shares' arg at the stock's maximum shares. This'll prevent\r\n // hanging in the case when a really big number is passed in\r\n shares = Math.min(shares, stock.maxShares);\r\n\r\n const isLong = (posType === PositionTypes.Long);\r\n\r\n let currPrice = stock.price;\r\n function processPriceMovement() {\r\n if (isLong) {\r\n currPrice *= calculateDecreasingPriceMovement(stock)!;\r\n } else {\r\n currPrice *= calculateIncreasingPriceMovement(stock)!;\r\n }\r\n }\r\n\r\n // No price/forecast movement\r\n if (shares <= stock.shareTxUntilMovement) {\r\n stock.shareTxUntilMovement -= shares;\r\n if (stock.shareTxUntilMovement <= 0) {\r\n stock.shareTxUntilMovement = stock.shareTxForMovement;\r\n processPriceMovement();\r\n stock.changePrice(currPrice);\r\n stock.otlkMag -= (forecastChangePerPriceMovement);\r\n }\r\n\r\n return;\r\n }\r\n\r\n // Calculate how many iterations of price changes we need to account for\r\n let remainingShares = shares - stock.shareTxUntilMovement;\r\n let numIterations = 1 + Math.ceil(remainingShares / stock.shareTxForMovement);\r\n\r\n for (let i = 1; i < numIterations; ++i) {\r\n processPriceMovement();\r\n }\r\n\r\n stock.shareTxUntilMovement = stock.shareTxForMovement - ((shares - stock.shareTxUntilMovement) % stock.shareTxForMovement);\r\n if (stock.shareTxUntilMovement === stock.shareTxForMovement || stock.shareTxUntilMovement <= 0) {\r\n ++numIterations;\r\n stock.shareTxUntilMovement = stock.shareTxForMovement;\r\n processPriceMovement();\r\n }\r\n stock.changePrice(currPrice);\r\n\r\n // Forecast always decreases in magnitude\r\n const forecastChange = Math.min(5, forecastChangePerPriceMovement * (numIterations - 1));\r\n stock.otlkMag -= forecastChange;\r\n if (stock.otlkMag < 0) {\r\n stock.b = !stock.b;\r\n stock.otlkMag = Math.abs(stock.otlkMag);\r\n }\r\n}\r\n\r\n/**\r\n * Calculate the maximum number of shares of a stock that can be purchased.\r\n * Handles mid-transaction price movements, both L and S positions, etc.\r\n * Used for the \"Buy Max\" button in the UI\r\n * @param {Stock} stock - Stock being purchased\r\n * @param {PositionTypes} posType - Long or short position\r\n * @param {number} money - Amount of money player has\r\n * @returns maximum number of shares that the player can purchase\r\n */\r\nexport function calculateBuyMaxAmount(stock: Stock, posType: PositionTypes, money: number): number {\r\n if (!(stock instanceof Stock)) { return 0; }\r\n\r\n const isLong = (posType === PositionTypes.Long);\r\n\r\n const increasingMvmt = calculateIncreasingPriceMovement(stock);\r\n const decreasingMvmt = calculateDecreasingPriceMovement(stock);\r\n if (increasingMvmt == null || decreasingMvmt == null) { return 0; }\r\n\r\n let remainingMoney = money - CONSTANTS.StockMarketCommission;\r\n let currPrice = isLong ? stock.getAskPrice() : stock.getBidPrice();\r\n\r\n // No price movement\r\n const firstIterationCost = stock.shareTxUntilMovement * currPrice;\r\n if (remainingMoney < firstIterationCost) {\r\n return Math.floor(remainingMoney / currPrice);\r\n }\r\n\r\n // We'll avoid any accidental infinite loops by having a hardcoded maximum number of\r\n // iterations\r\n let numShares = stock.shareTxUntilMovement;\r\n remainingMoney -= firstIterationCost;\r\n for (let i = 0; i < 10e3; ++i) {\r\n if (isLong) {\r\n currPrice *= increasingMvmt;\r\n } else {\r\n currPrice *= decreasingMvmt;\r\n }\r\n\r\n const affordableShares = Math.floor(remainingMoney / currPrice);\r\n const actualShares = Math.min(stock.shareTxForMovement, affordableShares);\r\n\r\n // Can't afford any more, so we're done\r\n if (actualShares <= 0) { break; }\r\n\r\n numShares += actualShares;\r\n\r\n let cost = actualShares * currPrice;\r\n remainingMoney -= cost;\r\n\r\n if (remainingMoney <= 0) { break; }\r\n }\r\n\r\n return Math.floor(numShares);\r\n}\r\n","export * from \"./Netscript/StaticRamCalculationTests\";\r\nexport * from \"./StockMarketTests\";\r\n","export enum OrderTypes {\r\n LimitBuy = \"Limit Buy Order\",\r\n LimitSell = \"Limit Sell Order\",\r\n StopBuy = \"Stop Buy Order\",\r\n StopSell = \"Stop Sell Order\"\r\n}\r\n","import { IMinMaxRange } from \"../types\";\r\nimport {\r\n Generic_fromJSON,\r\n Generic_toJSON,\r\n Reviver\r\n} from \"../../utils/JSONReviver\";\r\nimport { getRandomInt } from \"../../utils/helpers/getRandomInt\";\r\n\r\nexport interface IConstructorParams {\r\n b: boolean;\r\n initPrice: number | IMinMaxRange;\r\n marketCap: number;\r\n mv: number | IMinMaxRange;\r\n name: string;\r\n otlkMag: number;\r\n spreadPerc: number | IMinMaxRange;\r\n shareTxForMovement: number | IMinMaxRange;\r\n symbol: string;\r\n}\r\n\r\nconst defaultConstructorParams: IConstructorParams = {\r\n b: true,\r\n initPrice: 10e3,\r\n marketCap: 1e12,\r\n mv: 1,\r\n name: \"\",\r\n otlkMag: 0,\r\n spreadPerc: 0,\r\n shareTxForMovement: 1e6,\r\n symbol: \"\",\r\n}\r\n\r\n// Helper function that convert a IMinMaxRange to a number\r\nfunction toNumber(n: number | IMinMaxRange): number {\r\n let value: number;\r\n switch (typeof n) {\r\n case \"number\": {\r\n return n;\r\n }\r\n case \"object\": {\r\n const range = n;\r\n value = getRandomInt(range.min, range.max);\r\n break;\r\n }\r\n default:\r\n throw Error(`Do not know how to convert the type '${typeof n}' to a number`);\r\n }\r\n\r\n if (typeof n === \"object\" && typeof n.divisor === \"number\") {\r\n return value / n.divisor;\r\n }\r\n\r\n return value;\r\n}\r\n\r\n/**\r\n * Represents the valuation of a company in the World Stock Exchange.\r\n */\r\nexport class Stock {\r\n /**\r\n * Initializes a Stock from a JSON save state\r\n */\r\n static fromJSON(value: any): Stock {\r\n return Generic_fromJSON(Stock, value.data);\r\n }\r\n\r\n /**\r\n * Bear or bull (more likely to go up or down, based on otlkMag)\r\n */\r\n b: boolean;\r\n\r\n /**\r\n * Maximum price of a stock (per share)\r\n */\r\n readonly cap: number;\r\n\r\n /**\r\n * Stocks previous share price\r\n */\r\n lastPrice: number;\r\n\r\n /**\r\n * Maximum number of shares that player can own (both long and short combined)\r\n */\r\n readonly maxShares: number;\r\n\r\n /**\r\n * Maximum volatility\r\n */\r\n readonly mv: number;\r\n\r\n /**\r\n * Name of the company that the stock is for\r\n */\r\n readonly name: string;\r\n\r\n /**\r\n * Outlook magnitude. Represents the stock's forecast and likelihood\r\n * of increasing/decreasing (based on whether its in bear or bull mode)\r\n */\r\n otlkMag: number;\r\n\r\n /**\r\n * Average price of stocks that the player owns in the LONG position\r\n */\r\n playerAvgPx: number;\r\n\r\n /**\r\n * Average price of stocks that the player owns in the SHORT position\r\n */\r\n playerAvgShortPx: number;\r\n\r\n /**\r\n * Number of shares the player owns in the LONG position\r\n */\r\n playerShares: number;\r\n\r\n /**\r\n * Number of shares the player owns in the SHORT position\r\n */\r\n playerShortShares: number;\r\n\r\n /**\r\n * Stock's share price\r\n */\r\n price: number;\r\n\r\n /**\r\n * Percentage by which the stock's price changes for a transaction-induced\r\n * price movement.\r\n */\r\n readonly priceMovementPerc: number;\r\n\r\n /**\r\n * How many shares need to be transacted in order to trigger a price movement\r\n */\r\n readonly shareTxForMovement: number;\r\n\r\n /**\r\n * How many share transactions remaining until a price movement occurs\r\n */\r\n shareTxUntilMovement: number;\r\n\r\n /**\r\n * Spread percentage. The bid/ask prices for this stock are N% above or below\r\n * the \"real price\" to emulate spread.\r\n */\r\n readonly spreadPerc: number;\r\n\r\n /**\r\n * The stock's ticker symbol\r\n */\r\n readonly symbol: string;\r\n\r\n /**\r\n * Total number of shares of this stock\r\n * This is different than maxShares, as this is like authorized stock while\r\n * maxShares is outstanding stock.\r\n */\r\n readonly totalShares: number;\r\n\r\n constructor(p: IConstructorParams = defaultConstructorParams) {\r\n this.name = p.name;\r\n this.symbol = p.symbol;\r\n this.price = toNumber(p.initPrice);\r\n this.lastPrice = this.price;\r\n this.playerShares = 0;\r\n this.playerAvgPx = 0;\r\n this.playerShortShares = 0;\r\n this.playerAvgShortPx = 0;\r\n this.mv = toNumber(p.mv);\r\n this.b = p.b;\r\n this.otlkMag = p.otlkMag;\r\n this.cap = getRandomInt(this.price * 1e3, this.price * 25e3);\r\n this.spreadPerc = toNumber(p.spreadPerc);\r\n this.priceMovementPerc = this.spreadPerc / (getRandomInt(10, 30) / 10);\r\n this.shareTxForMovement = toNumber(p.shareTxForMovement);\r\n this.shareTxUntilMovement = this.shareTxForMovement;\r\n\r\n // Total shares is determined by market cap, and is rounded to nearest 100k\r\n let totalSharesUnrounded: number = (p.marketCap / this.price);\r\n this.totalShares = Math.round(totalSharesUnrounded / 1e5) * 1e5;\r\n\r\n // Max Shares (Outstanding shares) is a percentage of total shares\r\n const outstandingSharePercentage: number = 0.2;\r\n this.maxShares = Math.round((this.totalShares * outstandingSharePercentage) / 1e5) * 1e5;\r\n }\r\n\r\n changePrice(newPrice: number): void {\r\n this.lastPrice = this.price;\r\n this.price = newPrice;\r\n }\r\n\r\n /**\r\n * Return the price at which YOUR stock is bought (market ask price). Accounts for spread\r\n */\r\n getAskPrice(): number {\r\n return this.price * (1 + (this.spreadPerc / 100));\r\n }\r\n\r\n /**\r\n * Return the price at which YOUR stock is sold (market bid price). Accounts for spread\r\n */\r\n getBidPrice(): number {\r\n return this.price * (1 - (this.spreadPerc / 100));\r\n }\r\n\r\n /**\r\n * Serialize the Stock to a JSON save state.\r\n */\r\n toJSON(): any {\r\n return Generic_toJSON(\"Stock\", this);\r\n }\r\n}\r\n\r\nReviver.constructors.Stock = Stock;\r\n","/**\r\n * Generic Game Constants\r\n *\r\n * Constants for specific mechanics or features will NOT be here.\r\n */\r\nimport { IMap } from \"./types\";\r\n\r\nexport let CONSTANTS: IMap = {\r\n Version: \"0.46.3\",\r\n\r\n\t/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience\r\n * and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then\r\n * the player will have this level assuming no multipliers. Multipliers can cause skills to go above this.\r\n */\r\n\tMaxSkillLevel: \t\t\t975,\r\n\r\n // Milliseconds per game cycle\r\n MilliPerCycle: 200,\r\n\r\n // How much reputation is needed to join a megacorporation's faction\r\n CorpFactionRepRequirement: 200e3,\r\n\r\n // Base RAM costs\r\n BaseCostFor1GBOfRamHome: 32000,\r\n BaseCostFor1GBOfRamServer: 55000, //1 GB of RAM\r\n\r\n // Cost to travel to another city\r\n TravelCost: 200e3,\r\n\r\n // Faction and Company favor-related things\r\n BaseFavorToDonate: 150,\r\n DonateMoneyToRepDivisor: 1e6,\r\n FactionReputationToFavorBase: 500,\r\n FactionReputationToFavorMult: 1.02,\r\n CompanyReputationToFavorBase: 500,\r\n CompanyReputationToFavorMult: 1.02,\r\n\r\n // NeuroFlux Governor Augmentation cost multiplier\r\n NeuroFluxGovernorLevelMult: 1.14,\r\n\r\n NumNetscriptPorts: 20,\r\n\r\n // Server-related constants\r\n HomeComputerMaxRam: 1073741824, // 2 ^ 30\r\n ServerBaseGrowthRate: 1.03, // Unadjusted Growth rate\r\n ServerMaxGrowthRate: 1.0035, // Maximum possible growth rate (max rate accounting for server security)\r\n ServerFortifyAmount: 0.002, // Amount by which server's security increases when its hacked/grown\r\n ServerWeakenAmount: 0.05, // Amount by which server's security decreases when weakened\r\n\r\n PurchasedServerLimit: 25,\r\n PurchasedServerMaxRam: 1048576, // 2^20\r\n\r\n // Augmentation Constants\r\n AugmentationCostMultiplier: 5, // Used for balancing costs without having to readjust every Augmentation cost\r\n AugmentationRepMultiplier: 2.5, // Used for balancing rep cost without having to readjust every value\r\n MultipleAugMultiplier: 1.9,\r\n\r\n // TOR Router\r\n TorRouterCost: 200e3,\r\n\r\n // Infiltration\r\n InfiltrationBribeBaseAmount: 100e3, //Amount per clearance level\r\n InfiltrationMoneyValue: 5e3, //Convert \"secret\" value to money\r\n InfiltrationRepValue: 1.4, //Convert \"secret\" value to faction reputation\r\n InfiltrationExpPow: 0.8,\r\n\r\n // Stock market\r\n WSEAccountCost: 200e6,\r\n TIXAPICost: 5e9,\r\n MarketData4SCost: 1e9,\r\n MarketDataTixApi4SCost: 25e9,\r\n StockMarketCommission: 100e3,\r\n\r\n // Hospital/Health\r\n HospitalCostPerHp: 100e3,\r\n\r\n // Intelligence-related constants\r\n IntelligenceCrimeWeight: 0.05, // Weight for how much int affects crime success rates\r\n IntelligenceInfiltrationWeight: 0.1, // Weight for how much int affects infiltration success rates\r\n IntelligenceCrimeBaseExpGain: 0.001,\r\n IntelligenceProgramBaseExpGain: 500, // Program required hack level divided by this to determine int exp gain\r\n IntelligenceTerminalHackBaseExpGain: 200, // Hacking exp divided by this to determine int exp gain\r\n IntelligenceSingFnBaseExpGain: 0.002,\r\n IntelligenceClassBaseExpGain: 0.000001,\r\n IntelligenceHackingMissionBaseExpGain: 0.03, // Hacking Mission difficulty multiplied by this to get exp gain\r\n\r\n // Hacking Missions\r\n // TODO Move this into Hacking Mission implementation\r\n HackingMissionRepToDiffConversion: 10000, // Faction rep is divided by this to get mission difficulty\r\n HackingMissionRepToRewardConversion: 7, // Faction rep divided byt his to get mission rep reward\r\n HackingMissionSpamTimeIncrease: 25000, // How much time limit increase is gained when conquering a Spam Node (ms)\r\n HackingMissionTransferAttackIncrease: 1.05, // Multiplier by which the attack for all Core Nodes is increased when conquering a Transfer Node\r\n HackingMissionMiscDefenseIncrease: 1.05, // The amount by which every misc node's defense is multiplied when one is conquered\r\n HackingMissionDifficultyToHacking: 135, // Difficulty is multiplied by this to determine enemy's \"hacking\" level (to determine effects of scan/attack, etc)\r\n HackingMissionHowToPlay: \"Hacking missions are a minigame that, if won, will reward you with faction reputation.

\" +\r\n \"In this game you control a set of Nodes and use them to try and defeat an enemy. Your Nodes \" +\r\n \"are colored blue, while the enemy's are red. There are also other nodes on the map colored gray \" +\r\n \"that initially belong to neither you nor the enemy. The goal of the game is \" +\r\n \"to capture all of the enemy's Database nodes within the time limit. \" +\r\n \"If you fail to do this, you will lose.

\" +\r\n \"Each Node has three stats: Attack, Defense, and HP. There are five different actions that \" +\r\n \"a Node can take:

\" +\r\n \"Attack - Targets an enemy Node and lowers its HP. The effectiveness is determined by the owner's Attack, the Player's \" +\r\n \"hacking level, and the enemy's defense.

\" +\r\n \"Scan - Targets an enemy Node and lowers its Defense. The effectiveness is determined by the owner's Attack, the Player's hacking level, and the \" +\r\n \"enemy's defense.

\" +\r\n \"Weaken - Targets an enemy Node and lowers its Attack. The effectiveness is determined by the owner's Attack, the Player's hacking level, and the enemy's \" +\r\n \"defense.

\" +\r\n \"Fortify - Raises the Node's Defense. The effectiveness is determined by your hacking level.

\" +\r\n \"Overflow - Raises the Node's Attack but lowers its Defense. The effectiveness is determined by your hacking level.

\" +\r\n \"Note that when determining the effectiveness of the above actions, the TOTAL Attack or Defense of the team is used, not just the \" +\r\n \"Attack/Defense of the individual Node that is performing the action.

\" +\r\n \"To capture a Node, you must lower its HP down to 0.

\" +\r\n \"There are six different types of Nodes:

\" +\r\n \"CPU Core - These are your main Nodes that are used to perform actions. Capable of performing every action

\" +\r\n \"Firewall - Nodes with high defense. These Nodes can 'Fortify'

\" +\r\n \"Database - A special type of Node. The player's objective is to conquer all of the enemy's Database Nodes within \" +\r\n \"the time limit. These Nodes cannot perform any actions

\" +\r\n \"Spam - Conquering one of these Nodes will slow the enemy's trace, giving the player additional time to complete \" +\r\n \"the mission. These Nodes cannot perform any actions

\" +\r\n \"Transfer - Conquering one of these nodes will increase the Attack of all of your CPU Cores by a small fixed percentage. \" +\r\n \"These Nodes are capable of performing every action except the 'Attack' action

\" +\r\n \"Shield - Nodes with high defense. These Nodes can 'Fortify'

\" +\r\n \"To assign an action to a Node, you must first select one of your Nodes. This can be done by simply clicking on it. Double-clicking \" +\r\n \"a node will select all of your Nodes of the same type (e.g. select all CPU Core Nodes or all Transfer Nodes). Note that only Nodes \" +\r\n \"that can perform actions (CPU Core, Transfer, Shield, Firewall) can be selected. Selected Nodes will be denoted with a white highlight. After selecting a Node or multiple Nodes, \" +\r\n \"select its action using the Action Buttons near the top of the screen. Every action also has a corresponding keyboard \" +\r\n \"shortcut.

\" +\r\n \"For certain actions such as attacking, scanning, and weakening, the Node performing the action must have a target. To target \" +\r\n \"another node, simply click-and-drag from the 'source' Node to a target. A Node can only have one target, and you can target \" +\r\n \"any Node that is adjacent to one of your Nodes (immediately above, below, or to the side. NOT diagonal). Furthermore, only CPU Cores and Transfer Nodes \" +\r\n \"can target, since they are the only ones that can perform the related actions. To remove a target, you can simply click on the line that represents \" +\r\n \"the connection between one of your Nodes and its target. Alternatively, you can select the 'source' Node and click the 'Drop Connection' button, \" +\r\n \"or press 'd'.

\" +\r\n \"Other Notes:

\" +\r\n \"-Whenever a miscellenaous Node (not owned by the player or enemy) is conquered, the defense of all remaining miscellaneous Nodes that \" +\r\n \"are not actively being targeted will increase by a fixed percentage.

\" +\r\n \"-Whenever a Node is conquered, its stats are significantly reduced

\" +\r\n \"-Miscellaneous Nodes slowly raise their defense over time

\" +\r\n \"-Nodes slowly regenerate health over time.\",\r\n\r\n // Time-related constants\r\n MillisecondsPer20Hours: 72000000,\r\n GameCyclesPer20Hours: 72000000 / 200,\r\n\r\n MillisecondsPer10Hours: 36000000,\r\n GameCyclesPer10Hours: 36000000 / 200,\r\n\r\n MillisecondsPer8Hours: 28800000,\r\n GameCyclesPer8Hours: 28800000 / 200,\r\n\r\n MillisecondsPer4Hours: 14400000,\r\n GameCyclesPer4Hours: 14400000 / 200,\r\n\r\n MillisecondsPer2Hours: 7200000,\r\n GameCyclesPer2Hours: 7200000 / 200,\r\n\r\n MillisecondsPerHour: 3600000,\r\n GameCyclesPerHour: 3600000 / 200,\r\n\r\n MillisecondsPerHalfHour: 1800000,\r\n GameCyclesPerHalfHour: 1800000 / 200,\r\n\r\n MillisecondsPerQuarterHour: 900000,\r\n GameCyclesPerQuarterHour: 900000 / 200,\r\n\r\n MillisecondsPerFiveMinutes: 300000,\r\n GameCyclesPerFiveMinutes: 300000 / 200,\r\n\r\n // Player Work & Action\r\n FactionWorkHacking: \"Faction Hacking Work\",\r\n FactionWorkField: \"Faction Field Work\",\r\n FactionWorkSecurity: \"Faction Security Work\",\r\n\r\n WorkTypeCompany: \"Working for Company\",\r\n WorkTypeCompanyPartTime: \"Working for Company part-time\",\r\n WorkTypeFaction: \"Working for Faction\",\r\n WorkTypeCreateProgram: \"Working on Create a Program\",\r\n WorkTypeStudyClass: \"Studying or Taking a class at university\",\r\n WorkTypeCrime: \"Committing a crime\",\r\n\r\n ClassStudyComputerScience: \"studying Computer Science\",\r\n ClassDataStructures: \"taking a Data Structures course\",\r\n ClassNetworks: \"taking a Networks course\",\r\n ClassAlgorithms: \"taking an Algorithms course\",\r\n ClassManagement: \"taking a Management course\",\r\n ClassLeadership: \"taking a Leadership course\",\r\n ClassGymStrength: \"training your strength at a gym\",\r\n ClassGymDefense: \"training your defense at a gym\",\r\n ClassGymDexterity: \"training your dexterity at a gym\",\r\n ClassGymAgility: \"training your agility at a gym\",\r\n\r\n ClassDataStructuresBaseCost: 40,\r\n ClassNetworksBaseCost: 80,\r\n ClassAlgorithmsBaseCost: 320,\r\n ClassManagementBaseCost: 160,\r\n ClassLeadershipBaseCost: 320,\r\n ClassGymBaseCost: 120,\r\n\r\n CrimeShoplift: \"shoplift\",\r\n CrimeRobStore: \"rob a store\",\r\n CrimeMug: \"mug someone\",\r\n CrimeLarceny: \"commit larceny\",\r\n CrimeDrugs: \"deal drugs\",\r\n CrimeBondForgery: \"forge corporate bonds\",\r\n CrimeTraffickArms: \"traffick illegal arms\",\r\n CrimeHomicide: \"commit homicide\",\r\n CrimeGrandTheftAuto: \"commit grand theft auto\",\r\n CrimeKidnap: \"kidnap someone for ransom\",\r\n CrimeAssassination: \"assassinate a high-profile target\",\r\n CrimeHeist: \"pull off the ultimate heist\",\r\n\r\n // Coding Contract\r\n // TODO Move this into Coding contract impelmentation?\r\n CodingContractBaseFactionRepGain: 2500,\r\n CodingContractBaseCompanyRepGain: 4000,\r\n CodingContractBaseMoneyGain: 75e6,\r\n\r\n // BitNode/Source-File related stuff\r\n TotalNumBitNodes: 24,\r\n\r\n LatestUpdate:\r\n `\r\n v0.47.0\r\n * Stock Market changes:\r\n ** Implemented spread. Stock's now have bid and ask prices at which transactions occur\r\n ** Large transactions will now influence a stock's price and forecast\r\n ** This \"influencing\" can take effect in the middle of a transaction\r\n ** See documentation for more details on these changes\r\n ** Added getStockAskPrice(), getStockBidPrice() Netscript functions to the TIX API\r\n ** Added getStockPurchaseCost(), getStockSaleGain() Netscript functions to the TIX API\r\n\r\n * Re-sleeves can no longer have the NeuroFlux Governor augmentation\r\n ** This is just a temporary patch until the mechanic gets re-worked\r\n\r\n * Adjusted RAM costs of Netscript Singularity functions (mostly increased)\r\n * Netscript Singularity functions no longer cost extra RAM outside of BitNode-4\r\n * Corporation employees no longer have an \"age\" stat\r\n * Bug Fix: Corporation employees stats should no longer become negative\r\n * Bug Fix: Fixed sleeve.getInformation() throwing error in certain scenarios\r\n * Bug Fix: Coding contracts should no longer generate on the w0r1d_d43m0n server\r\n * Bug Fix: Duplicate Sleeves now properly have access to all Augmentations if you have a gang\r\n * Bug Fix: getAugmentationsFromFaction() & purchaseAugmentation() functions should now work properly if you have a gang\r\n * Bug Fix: Fixed issue that caused messages (.msg) to be sent when refreshing/reloading the game\r\n * Bug Fix: Purchasing hash upgrades for Bladeburner/Corporation when you don't actually have access to those mechanics no longer gives hashes\r\n * Bug Fix: run(), exec(), and spawn() Netscript functions now throw if called with 0 threads\r\n * Bug Fix: Faction UI should now automatically update reputation\r\n `\r\n}\r\n","/**\r\n * Represents a Limit or Buy Order on the stock market. Does not represent\r\n * a Market Order since those are just executed immediately\r\n */\r\nimport { OrderTypes } from \"./data/OrderTypes\";\r\nimport { PositionTypes } from \"./data/PositionTypes\";\r\n\r\nimport {\r\n Generic_fromJSON,\r\n Generic_toJSON,\r\n Reviver,\r\n} from \"../../utils/JSONReviver\";\r\n\r\nexport class Order {\r\n /**\r\n * Initializes a Order from a JSON save state\r\n */\r\n static fromJSON(value: any): Order {\r\n return Generic_fromJSON(Order, value.data);\r\n }\r\n\r\n readonly pos: PositionTypes;\r\n readonly price: number;\r\n shares: number;\r\n readonly stockSymbol: string;\r\n readonly type: OrderTypes;\r\n\r\n constructor(stockSymbol: string=\"\", shares: number=0, price: number=0, typ: OrderTypes=OrderTypes.LimitBuy, pos: PositionTypes=PositionTypes.Long) {\r\n // Validate arguments\r\n let invalidArgs: boolean = false;\r\n if (typeof shares !== \"number\" || typeof price !== \"number\") {\r\n invalidArgs = true;\r\n }\r\n if (isNaN(shares) || isNaN(price)) {\r\n invalidArgs = true;\r\n }\r\n if (typeof stockSymbol !== \"string\") {\r\n invalidArgs = true;\r\n }\r\n if (invalidArgs) {\r\n throw new Error(`Invalid constructor paramters for Order`);\r\n }\r\n\r\n this.stockSymbol = stockSymbol;\r\n this.shares = shares;\r\n this.price = price;\r\n this.type = typ;\r\n this.pos = pos;\r\n }\r\n\r\n /**\r\n * Serialize the Order to a JSON save state.\r\n */\r\n toJSON(): any {\r\n return Generic_toJSON(\"Order\", this);\r\n }\r\n}\r\n\r\nReviver.constructors.Order = Order;\r\n"],"sourceRoot":""} \ No newline at end of file diff --git a/test/tests.css b/test/tests.css deleted file mode 100644 index c5f22a196..000000000 --- a/test/tests.css +++ /dev/null @@ -1,4889 +0,0 @@ -/* COLORS */ -/* Attributes */ -/** - * Customized styling for the Code Mirror editor - */ -#codemirror-form-wrapper { - height: 80%; - margin: 10px 0px 0px 6px; } - -.CodeMirror { - height: 100%; - width: 100%; - border: 2px solid var(--my-highlight-color); - z-index: 1; - font-family: "Lucida Console", "Lucida Sans Unicode", "Fira Mono", "Consolas", "Courier New", Courier, monospace, "Times New Roman"; - font-size: 16px; } - -/** - * Highlight matches - */ -.cm-matchhighlight { - background-color: #8F908A; } - -.CodeMirror-selection-highlight-scrollbar { - background-color: #8F908A; } - -/** - * Show Invisibles - */ -.cm-whitespace::before { - position: absolute; - pointer-events: none; - color: #404F7D; } - -/** - * Vim command display - */ -#codemirror-vim-command-display-wrapper { - background-color: white; - font-size: 13px; - height: 30px; - margin-left: 6px; } - -/* COLORS */ -/* Attributes */ -/* COLORS */ -/* Attributes */ -* { - font-size: 16px; - font-family: "Lucida Console", "Lucida Sans Unicode", "Fira Mono", "Consolas", "Courier New", Courier, monospace, "Times New Roman"; } - -*, -*:before, -*:after { - margin: 0; - padding: 0; - box-sizing: border-box; - vertical-align: top; } - -:root { - --my-font-color: #6f3; - --my-background-color: #000; - --my-highlight-color: #fff; - --my-prompt-color: #f92672; } - -body { - background-color: var(--my-background-color); } - -p, -pre, -h2, -.text { - color: var(--my-font-color); } - -h1 { - font-size: 22px; - color: var(--my-font-color); } - -ul { - padding: 2px; - list-style-type: none; } - -li { - list-style-type: none; } - -#entire-game-container { - background-color: transparent; } - -/* Disable border highlight on elements */ -input:focus, -textarea:focus, -button:focus, -td:focus, -tr:focus { - outline: none; } - -/* Make html links ("a" elements) nice looking buttons with this class */ -a:link, -a:visited { - color: #fff; } - -.dropdown { - color: #fff; - background-color: #000; } - -.text-input { - color: #fff; - background-color: #000; - border-style: solid; - border-width: 1px; - border-color: white; } - -/* Notification icon (for create program right now only) */ -#create-program-tab { - position: relative; } - -#create-program-notification { - font-size: 10px; - position: absolute; - /* Position the badge within the relatively positioned button */ - top: 0; - right: 0; } - -.notification-on { - background-color: #fa3e3e; - color: #fff; - border-radius: 2px; - padding: 1px 3px; } - -.notification-off { - background-color: #333; - color: #333; - border-radius: 0; - padding: 0; } - -/* help tip. Question mark that opens popup with info/details */ -.help-tip { - background-color: black; - border: 1px solid #fff; - border-radius: 5px; - color: #fff; - content: '?'; - display: inline-block; - margin-left: 3px; - padding: 1px; } - -.help-tip-big { - content: '?'; - padding: 3px; - margin-left: 3px; - color: #fff; - border: 1px solid #fff; - border-radius: 8px; - display: inline-block; } - -.help-tip:hover, -.help-tip-big:hover { - background-color: #888; } - -.help-tip:active, -.help-tip-big:active { - -webkit-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6); - -moz-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6); - box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.6); } - -/* Flashing button (Red) */ -@-webkit-keyframes glowing { - 0% { - background-color: #b20000; - -webkit-box-shadow: 0 0 3px #b20000; } - 50% { - background-color: #f00; - -webkit-box-shadow: 0 0 40px #f00; } - 100% { - background-color: #b20000; - -webkit-box-shadow: 0 0 3px #b20000; } } - -@-moz-keyframes glowing { - 0% { - background-color: #b20000; - -moz-box-shadow: 0 0 3px #b20000; } - 50% { - background-color: #f00; - -moz-box-shadow: 0 0 40px #f00; } - 100% { - background-color: #b20000; - -moz-box-shadow: 0 0 3px #b20000; } } - -@-o-keyframes glowing { - 0% { - background-color: #b20000; - box-shadow: 0 0 3px #b20000; } - 50% { - background-color: #f00; - box-shadow: 0 0 40px #f00; } - 100% { - background-color: #b20000; - box-shadow: 0 0 3px #b20000; } } - -@keyframes glowing { - 0% { - background-color: #b20000; - box-shadow: 0 0 3px #b20000; } - 50% { - background-color: #f00; - box-shadow: 0 0 40px #f00; } - 100% { - background-color: #b20000; - box-shadow: 0 0 3px #b20000; } } - -.flashing-button { - -webkit-animation: glowing 1500ms infinite; - -moz-animation: glowing 1500ms infinite; - -o-animation: glowing 1500ms infinite; - animation: glowing 1500ms infinite; } - -/* Blinking Cursor */ -/* ----- blinking cursor animation ----- */ -.typed-cursor { - opacity: 1; - -webkit-animation: blink 0.95s infinite; - -moz-animation: blink 0.95s infinite; - -ms-animation: blink 0.95s infinite; - -o-animation: blink 0.95s infinite; - animation: blink 0.95s infinite; } - -@-keyframes blink { - 0% { - opacity: 1; } - 50% { - opacity: 0; } - 100% { - opacity: 1; } } - -@-webkit-keyframes blink { - 0% { - opacity: 1; } - 50% { - opacity: 0; } - 100% { - opacity: 1; } } - -@-moz-keyframes blink { - 0% { - opacity: 1; } - 50% { - opacity: 0; } - 100% { - opacity: 1; } } - -@-ms-keyframes blink { - 0% { - opacity: 1; } - 50% { - opacity: 0; } - 100% { - opacity: 1; } } - -@-o-keyframes blink { - 0% { - opacity: 1; } - 50% { - opacity: 0; } - 100% { - opacity: 1; } } - -/* Status text */ -@-webkit-keyframes status-text { - from { - opacity: 1; } - to { - opacity: 0; } } - -.status-text { - display: inline-block; - position: fixed; - z-index: 2; - -webkit-animation: status-text 3s 1; } - -#status-text-container { - background-color: transparent; } - -#status-text { - background-color: transparent; - bottom: 0; - color: #fff; - display: none; - font-size: 20px; - margin-right: 14px; - opacity: 0; - padding: 4px; - right: 0; - top: 0; - width: auto; } - -/* Scan analyze links from AutoLink */ -.scan-analyze-link { - cursor: pointer; - color: #fff; - text-decoration: underline; } - .scan-analyze-link:hover { - text-decoration: none; } - -/* Accordion menus (Header with collapsible panel) */ -.accordion-header { - background-color: #444; - font-size: 20px; - color: #fff; - margin: 6px 6px 0 6px; - padding: 4px 6px; - cursor: pointer; - width: 80%; - text-align: left; - border: none; - outline: none; - position: relative; } - .accordion-header.active, .accordion-header:hover { - background-color: #555; } - .accordion-header.active:hover { - background-color: #666; } - .accordion-header:after { - content: '\2795'; - /* "plus" sign (+) */ - font-size: 14px; - float: right; - color: transparent; - text-shadow: 0 0 0 #fff; - position: absolute; - bottom: 5px; - right: 6px; } - .accordion-header.active:after { - content: "\2796"; - /* "minus" sign (-) */ } - -.accordion-panel { - margin: 0 6px 6px 6px; - padding: 0 6px 6px 6px; - width: 75%; - margin-left: 5%; - display: none; - background-color: #555; - overflow-y: auto; - overflow-x: none; } - .accordion-panel div, .accordion-panel ul, .accordion-panel p, .accordion-panel ul > li { - background-color: #555; } - -/* override the global styling */ -#active-scripts-total-production-active, -#active-scripts-total-prod-aug-total, -#active-scripts-total-prod-aug-avg { - margin: 0; - padding: 0; } - -/* Helper Classes */ -.hacker-green { - color: #adff2f; } - -.money-gold { - color: #ffd700; } - -.light-yellow { - color: #faffdf; } - -.failure { - color: #ff2929; - text-shadow: 0 0 0 #ff2929; } - -.success { - color: #3adb76; - text-shadow: 0 0 0 #3adb76; } - -.physical-yellow { - color: #faffdf; } - -.charisma-purple { - color: #a671d1; } - -.smallfont { - font-size: 13px; } - -/* COLORS */ -/* Attributes */ -/* Styling for tooltip-style elements */ -/* Tool tips (when hovering over an element */ -.tooltip { - display: inline-block; - position: relative; - /* Positioned to left of element rather than right */ - /* Tooltip goes below cursor instead of above */ } - .tooltip .tooltiptext { - visibility: hidden; - width: 300px; - background-color: var(--my-background-color); - border: 2px solid var(--my-highlight-color); - color: #fff; - text-align: center; - padding: 4px; - left: 101%; - pointer-events: none; - position: absolute; - z-index: 99; } - .tooltip .tooltiptextleft { - visibility: hidden; - width: 300px; - background-color: var(--my-background-color); - border: 2px solid var(--my-highlight-color); - color: #fff; - text-align: center; - padding: 4px; - top: 50%; - left: 50%; - transform: translate(-100%, -100%); - /* Backwards compatibility */ - -webkit-transform: translate(-100%, -100%); - -moz-transform: translate(-100%, -100%); - -o-transform: translate(-100%, -100%); - -ms-transform: translate(-100%, -100%); - position: absolute; - z-index: 99; } - .tooltip .tooltiptextlow { - visibility: hidden; - width: 300px; - background-color: var(--my-background-color); - border: 2px solid var(--my-highlight-color); - color: #fff; - text-align: center; - padding: 4px; - left: 101%; - pointer-events: none; - position: absolute; - z-index: 99; - bottom: 25%; } - -/* Same thing as a normal tooltip except its a bit higher */ -.tooltip .tooltiptexthigh { - visibility: hidden; - width: 300px; - background-color: var(--my-background-color); - border: 2px solid var(--my-highlight-color); - color: #fff; - text-align: center; - padding: 4px; - left: 101%; - bottom: -25%; - position: absolute; - z-index: 99; } - -.tooltip:hover .tooltiptext, -.tooltip:hover .tooltiptexthigh, -.tooltip:hover .tooltiptextleft, -.tooltip:hover .tooltiptextlow { - visibility: visible; } - -/* COLORS */ -/* Attributes */ -/** - * Styling for all buttons - * - * Includes