mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-03 04:53:51 +01:00
CODEBASE: Validate AllGangs and StockMarket after loading with JSON.parse (#1783)
This commit is contained in:
parent
7d03a9ef32
commit
faed78cf2c
269
package-lock.json
generated
269
package-lock.json
generated
@ -24,6 +24,7 @@
|
|||||||
"acorn": "^8.11.3",
|
"acorn": "^8.11.3",
|
||||||
"acorn-jsx-walk": "^2.0.0",
|
"acorn-jsx-walk": "^2.0.0",
|
||||||
"acorn-walk": "^8.3.2",
|
"acorn-walk": "^8.3.2",
|
||||||
|
"ajv": "^8.17.1",
|
||||||
"arg": "^5.0.2",
|
"arg": "^5.0.2",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"better-react-mathjax": "^2.0.3",
|
"better-react-mathjax": "^2.0.3",
|
||||||
@ -2348,6 +2349,23 @@
|
|||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@eslint/eslintrc/node_modules/ajv": {
|
||||||
|
"version": "6.12.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
|
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@eslint/eslintrc/node_modules/argparse": {
|
"node_modules/@eslint/eslintrc/node_modules/argparse": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
@ -2381,6 +2399,13 @@
|
|||||||
"js-yaml": "bin/js-yaml.js"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@eslint/eslintrc/node_modules/type-fest": {
|
"node_modules/@eslint/eslintrc/node_modules/type-fest": {
|
||||||
"version": "0.20.2",
|
"version": "0.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
|
||||||
@ -3525,6 +3550,30 @@
|
|||||||
"resolve": "~1.19.0"
|
"resolve": "~1.19.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@microsoft/api-extractor-model/node_modules/ajv": {
|
||||||
|
"version": "6.12.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
|
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@microsoft/api-extractor-model/node_modules/json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@microsoft/api-extractor-model/node_modules/resolve": {
|
"node_modules/@microsoft/api-extractor-model/node_modules/resolve": {
|
||||||
"version": "1.19.0",
|
"version": "1.19.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
|
||||||
@ -3665,12 +3714,6 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@microsoft/api-extractor/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/@microsoft/api-extractor/node_modules/lru-cache": {
|
"node_modules/@microsoft/api-extractor/node_modules/lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
@ -3780,12 +3823,6 @@
|
|||||||
"url": "https://github.com/sponsors/epoberezkin"
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/@mui/base": {
|
"node_modules/@mui/base": {
|
||||||
"version": "5.0.0-beta.18",
|
"version": "5.0.0-beta.18",
|
||||||
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.18.tgz",
|
"resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.18.tgz",
|
||||||
@ -5772,15 +5809,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
"version": "6.12.6",
|
"version": "8.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||||
"dev": true,
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-uri": "^3.0.1",
|
||||||
"json-schema-traverse": "^0.4.1",
|
"json-schema-traverse": "^1.0.0",
|
||||||
"uri-js": "^4.2.2"
|
"require-from-string": "^2.0.2"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@ -5804,37 +5841,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ajv-formats/node_modules/ajv": {
|
|
||||||
"version": "8.12.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
|
||||||
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.1",
|
|
||||||
"json-schema-traverse": "^1.0.0",
|
|
||||||
"require-from-string": "^2.0.2",
|
|
||||||
"uri-js": "^4.2.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/ajv-keywords": {
|
|
||||||
"version": "3.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
|
||||||
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
|
||||||
"dev": true,
|
|
||||||
"peerDependencies": {
|
|
||||||
"ajv": "^6.9.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ansi-escapes": {
|
"node_modules/ansi-escapes": {
|
||||||
"version": "4.3.2",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||||
@ -6185,22 +6191,6 @@
|
|||||||
"webpack": ">=5"
|
"webpack": ">=5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-loader/node_modules/ajv": {
|
|
||||||
"version": "8.12.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
|
||||||
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.1",
|
|
||||||
"json-schema-traverse": "^1.0.0",
|
|
||||||
"require-from-string": "^2.0.2",
|
|
||||||
"uri-js": "^4.2.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/babel-loader/node_modules/ajv-keywords": {
|
"node_modules/babel-loader/node_modules/ajv-keywords": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||||
@ -6213,12 +6203,6 @@
|
|||||||
"ajv": "^8.8.2"
|
"ajv": "^8.8.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-loader/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/babel-loader/node_modules/schema-utils": {
|
"node_modules/babel-loader/node_modules/schema-utils": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
||||||
@ -7153,22 +7137,6 @@
|
|||||||
"webpack": "^5.1.0"
|
"webpack": "^5.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/copy-webpack-plugin/node_modules/ajv": {
|
|
||||||
"version": "8.17.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
|
||||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.3",
|
|
||||||
"fast-uri": "^3.0.1",
|
|
||||||
"json-schema-traverse": "^1.0.0",
|
|
||||||
"require-from-string": "^2.0.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/copy-webpack-plugin/node_modules/ajv-keywords": {
|
"node_modules/copy-webpack-plugin/node_modules/ajv-keywords": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||||
@ -7201,12 +7169,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/copy-webpack-plugin/node_modules/path-type": {
|
"node_modules/copy-webpack-plugin/node_modules/path-type": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz",
|
||||||
@ -8566,6 +8528,23 @@
|
|||||||
"url": "https://opencollective.com/eslint"
|
"url": "https://opencollective.com/eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint/node_modules/ajv": {
|
||||||
|
"version": "6.12.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
|
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/eslint/node_modules/ansi-styles": {
|
"node_modules/eslint/node_modules/ansi-styles": {
|
||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||||
@ -8673,6 +8652,13 @@
|
|||||||
"js-yaml": "bin/js-yaml.js"
|
"js-yaml": "bin/js-yaml.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eslint/node_modules/json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/eslint/node_modules/supports-color": {
|
"node_modules/eslint/node_modules/supports-color": {
|
||||||
"version": "7.2.0",
|
"version": "7.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||||
@ -8970,8 +8956,7 @@
|
|||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
"version": "3.3.2",
|
"version": "3.3.2",
|
||||||
@ -9016,8 +9001,7 @@
|
|||||||
"node_modules/fast-uri": {
|
"node_modules/fast-uri": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz",
|
||||||
"integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==",
|
"integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/fastest-levenshtein": {
|
"node_modules/fastest-levenshtein": {
|
||||||
"version": "1.0.16",
|
"version": "1.0.16",
|
||||||
@ -12964,10 +12948,10 @@
|
|||||||
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
|
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
|
||||||
},
|
},
|
||||||
"node_modules/json-schema-traverse": {
|
"node_modules/json-schema-traverse": {
|
||||||
"version": "0.4.1",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
"dev": true
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/json-stable-stringify-without-jsonify": {
|
"node_modules/json-stable-stringify-without-jsonify": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -16216,7 +16200,6 @@
|
|||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -16465,6 +16448,40 @@
|
|||||||
"url": "https://opencollective.com/webpack"
|
"url": "https://opencollective.com/webpack"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/schema-utils/node_modules/ajv": {
|
||||||
|
"version": "6.12.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
|
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/schema-utils/node_modules/ajv-keywords": {
|
||||||
|
"version": "3.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||||
|
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"ajv": "^6.9.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/schema-utils/node_modules/json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/select-hose": {
|
"node_modules/select-hose": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||||
@ -18213,22 +18230,6 @@
|
|||||||
"webpack": "^4.0.0 || ^5.0.0"
|
"webpack": "^4.0.0 || ^5.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack-dev-middleware/node_modules/ajv": {
|
|
||||||
"version": "8.12.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
|
||||||
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.1",
|
|
||||||
"json-schema-traverse": "^1.0.0",
|
|
||||||
"require-from-string": "^2.0.2",
|
|
||||||
"uri-js": "^4.2.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/webpack-dev-middleware/node_modules/ajv-keywords": {
|
"node_modules/webpack-dev-middleware/node_modules/ajv-keywords": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||||
@ -18241,12 +18242,6 @@
|
|||||||
"ajv": "^8.8.2"
|
"ajv": "^8.8.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/webpack-dev-middleware/node_modules/schema-utils": {
|
"node_modules/webpack-dev-middleware/node_modules/schema-utils": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
||||||
@ -18325,22 +18320,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack-dev-server/node_modules/ajv": {
|
|
||||||
"version": "8.12.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
|
||||||
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.1",
|
|
||||||
"json-schema-traverse": "^1.0.0",
|
|
||||||
"require-from-string": "^2.0.2",
|
|
||||||
"uri-js": "^4.2.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/webpack-dev-server/node_modules/ajv-keywords": {
|
"node_modules/webpack-dev-server/node_modules/ajv-keywords": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||||
@ -18353,12 +18332,6 @@
|
|||||||
"ajv": "^8.8.2"
|
"ajv": "^8.8.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack-dev-server/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/webpack-dev-server/node_modules/schema-utils": {
|
"node_modules/webpack-dev-server/node_modules/schema-utils": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
"acorn": "^8.11.3",
|
"acorn": "^8.11.3",
|
||||||
"acorn-jsx-walk": "^2.0.0",
|
"acorn-jsx-walk": "^2.0.0",
|
||||||
"acorn-walk": "^8.3.2",
|
"acorn-walk": "^8.3.2",
|
||||||
|
"ajv": "^8.17.1",
|
||||||
"arg": "^5.0.2",
|
"arg": "^5.0.2",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"better-react-mathjax": "^2.0.3",
|
"better-react-mathjax": "^2.0.3",
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { FactionName } from "@enums";
|
import { FactionName } from "@enums";
|
||||||
import { Reviver } from "../utils/GenericReviver";
|
import { Reviver } from "../utils/GenericReviver";
|
||||||
|
import { JsonSchemaValidator } from "../JsonSchema/JsonSchemaValidator";
|
||||||
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
|
|
||||||
interface GangTerritory {
|
interface GangTerritory {
|
||||||
power: number;
|
power: number;
|
||||||
territory: number;
|
territory: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDefaultAllGangs() {
|
export function getDefaultAllGangs() {
|
||||||
return {
|
return {
|
||||||
[FactionName.SlumSnakes]: {
|
[FactionName.SlumSnakes]: {
|
||||||
power: 1,
|
power: 1,
|
||||||
@ -46,7 +48,26 @@ export function resetGangs(): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function loadAllGangs(saveString: string): void {
|
export function loadAllGangs(saveString: string): void {
|
||||||
AllGangs = JSON.parse(saveString, Reviver);
|
let allGangsData: unknown;
|
||||||
|
let validate;
|
||||||
|
try {
|
||||||
|
allGangsData = JSON.parse(saveString, Reviver);
|
||||||
|
validate = JsonSchemaValidator.AllGangs;
|
||||||
|
if (!validate(allGangsData)) {
|
||||||
|
console.error("validate.errors:", validate.errors);
|
||||||
|
// validate.errors is an array of objects, so we need to use JSON.stringify.
|
||||||
|
throw new Error(JSON.stringify(validate.errors));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
console.error("Invalid AllGangsSave:", saveString);
|
||||||
|
resetGangs();
|
||||||
|
setTimeout(() => {
|
||||||
|
dialogBoxCreate(`Cannot load data of AllGangs. AllGangs is reset. Error: ${error}.`);
|
||||||
|
}, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AllGangs = allGangsData;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getClashWinChance(thisGang: string, otherGang: string): number {
|
export function getClashWinChance(thisGang: string, otherGang: string): number {
|
||||||
|
35
src/JsonSchema/Data/AllGangsSchema.ts
Normal file
35
src/JsonSchema/Data/AllGangsSchema.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import type { JSONSchemaType } from "ajv";
|
||||||
|
import type { AllGangs } from "../../Gang/AllGangs";
|
||||||
|
import { GangConstants } from "../../Gang/data/Constants";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we add/remove gangs, we must change 4 things:
|
||||||
|
* - src\Gang\AllGangs.ts: getDefaultAllGangs
|
||||||
|
* - src\Gang\data\Constants.ts: GangConstants.Names
|
||||||
|
* - src\Gang\data\power.ts: PowerMultiplier
|
||||||
|
* - Save file migration code.
|
||||||
|
*
|
||||||
|
* Gang code assumes that save data contains exactly gangs defined in these places.
|
||||||
|
*/
|
||||||
|
export const AllGangsSchema: JSONSchemaType<typeof AllGangs> = {
|
||||||
|
$schema: "http://json-schema.org/draft-07/schema#",
|
||||||
|
type: "object",
|
||||||
|
patternProperties: {
|
||||||
|
".*": {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
power: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
territory: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: ["power", "territory"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
propertyNames: {
|
||||||
|
enum: GangConstants.Names,
|
||||||
|
},
|
||||||
|
required: GangConstants.Names,
|
||||||
|
};
|
141
src/JsonSchema/Data/StockMarketSchema.ts
Normal file
141
src/JsonSchema/Data/StockMarketSchema.ts
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
import { OrderType, PositionType } from "@enums";
|
||||||
|
import { getKeyList } from "../../utils/helpers/getKeyList";
|
||||||
|
import { Stock } from "../../StockMarket/Stock";
|
||||||
|
import { Order } from "../../StockMarket/Order";
|
||||||
|
|
||||||
|
const stockObjectProperties = getKeyList(Stock);
|
||||||
|
const orderObjectProperties = getKeyList(Order);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It's intentional to not use JSONSchemaType here. The data structure of StockMarket is not suitable for the usage of
|
||||||
|
* JSONSchemaType. These are 2 biggest problems:
|
||||||
|
* - IStockMarket is an intersection type. In our case, satisfying TS's type-checking for JSONSchemaType is too hard.
|
||||||
|
* - Stock and Order are classes, not interfaces or types. In those classes, we have functions, but functions are not
|
||||||
|
* supported by JSON (without ugly hacks). Let's use the "Order" class as an example. The Order class has the toJSON
|
||||||
|
* function, so ajv forces us to define the "toJSON" property. If we define it, we have to give it a "type". In
|
||||||
|
* JavaScript, a function is just an object, so the naive solution is to use {type:"object"}. However, the generated
|
||||||
|
* validation code uses "typeof" to check the data. "typeof functionName" is "function", not "object", so ajv sees it as
|
||||||
|
* invalid data. There are some ways to work around this problem, but all of them are complicated. In the end,
|
||||||
|
* JSONSchemaType is only a utility type. If our schema is designed and tested properly, after the validation, we can
|
||||||
|
* typecast the data.
|
||||||
|
*/
|
||||||
|
export const StockMarketSchema = {
|
||||||
|
$schema: "http://json-schema.org/draft-07/schema#",
|
||||||
|
type: "object",
|
||||||
|
patternProperties: {
|
||||||
|
/**
|
||||||
|
* IStockMarket is an intersection type combining:
|
||||||
|
* - Record<string, Stock> [1]
|
||||||
|
* - {lastUpdate: number;Orders: IOrderBook;storedCycles: number;ticksUntilCycle: number;} [2]
|
||||||
|
*
|
||||||
|
* StockMarketSchema contains:
|
||||||
|
* - patternProperties: Defines [1]. The following regex matches all properties that are not in [2]. It defines the
|
||||||
|
* map of "Full stock name -> Stock".
|
||||||
|
* - properties: Define [2].
|
||||||
|
*
|
||||||
|
* Note that with [1], our code allows unknown stocks. Let's say the player loads a save file with this entry in
|
||||||
|
* [1]: UnknownCorp123 -> Stock with symbol UCP123. Although this stock is not in our list of "valid" stocks, we
|
||||||
|
* still process it normally. By "tolerating" unknown stocks, we allow loading a save file created in:
|
||||||
|
* - Old versions with unsupported stocks: In very old versions (v1.2.0 and older ones), the "full stock name" of
|
||||||
|
* "Joe's Guns" is "Joes Guns".
|
||||||
|
* - New versions with unknown stocks.
|
||||||
|
*/
|
||||||
|
"^(?!(lastUpdate|Orders|storedCycles|ticksUntilCycle))": {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
b: {
|
||||||
|
type: "boolean",
|
||||||
|
},
|
||||||
|
cap: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
lastPrice: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
maxShares: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
mv: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
otlkMag: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
otlkMagForecast: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
playerAvgPx: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
playerAvgShortPx: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
playerShares: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
playerShortShares: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
shareTxForMovement: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
shareTxUntilMovement: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
spreadPerc: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
symbol: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
totalShares: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: [...stockObjectProperties],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
lastUpdate: { type: "number" },
|
||||||
|
Orders: {
|
||||||
|
type: "object",
|
||||||
|
patternProperties: {
|
||||||
|
".*": {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
pos: {
|
||||||
|
type: "string",
|
||||||
|
enum: [PositionType.Long, PositionType.Short],
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
shares: {
|
||||||
|
type: "number",
|
||||||
|
},
|
||||||
|
stockSymbol: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: "string",
|
||||||
|
enum: [OrderType.LimitBuy, OrderType.LimitSell, OrderType.StopBuy, OrderType.StopSell],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
required: [...orderObjectProperties],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
storedCycles: { type: "number" },
|
||||||
|
ticksUntilCycle: { type: "number" },
|
||||||
|
},
|
||||||
|
required: ["lastUpdate", "Orders", "storedCycles", "ticksUntilCycle"],
|
||||||
|
};
|
10
src/JsonSchema/JsonSchemaValidator.ts
Normal file
10
src/JsonSchema/JsonSchemaValidator.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import Ajv from "ajv";
|
||||||
|
import { AllGangsSchema } from "./Data/AllGangsSchema";
|
||||||
|
import { StockMarketSchema } from "./Data/StockMarketSchema";
|
||||||
|
|
||||||
|
const ajv = new Ajv();
|
||||||
|
|
||||||
|
export const JsonSchemaValidator = {
|
||||||
|
AllGangs: ajv.compile(AllGangsSchema),
|
||||||
|
StockMarket: ajv.compile(StockMarketSchema),
|
||||||
|
};
|
@ -16,13 +16,19 @@ import { Reviver } from "../utils/GenericReviver";
|
|||||||
import { NetscriptContext } from "../Netscript/APIWrapper";
|
import { NetscriptContext } from "../Netscript/APIWrapper";
|
||||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||||
import { getRandomIntInclusive } from "../utils/helpers/getRandomIntInclusive";
|
import { getRandomIntInclusive } from "../utils/helpers/getRandomIntInclusive";
|
||||||
|
import { JsonSchemaValidator } from "../JsonSchema/JsonSchemaValidator";
|
||||||
|
import { Player } from "../Player";
|
||||||
|
|
||||||
export let StockMarket: IStockMarket = {
|
export function getDefaultEmptyStockMarket(): IStockMarket {
|
||||||
|
return {
|
||||||
lastUpdate: 0,
|
lastUpdate: 0,
|
||||||
Orders: {},
|
Orders: {},
|
||||||
storedCycles: 0,
|
storedCycles: 0,
|
||||||
ticksUntilCycle: 0,
|
ticksUntilCycle: 0,
|
||||||
} as IStockMarket; // Maps full stock name -> Stock object
|
} as IStockMarket;
|
||||||
|
}
|
||||||
|
|
||||||
|
export let StockMarket = getDefaultEmptyStockMarket(); // Maps full stock name -> Stock object
|
||||||
// Gross type, needs to be addressed
|
// Gross type, needs to be addressed
|
||||||
export const SymbolToStockMap: Record<string, Stock> = {}; // Maps symbol -> Stock object
|
export const SymbolToStockMap: Record<string, Stock> = {}; // Maps symbol -> Stock object
|
||||||
|
|
||||||
@ -130,23 +136,35 @@ export function cancelOrder(params: ICancelOrderParams, ctx?: NetscriptContext):
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function loadStockMarket(saveString: string): void {
|
export function loadStockMarket(saveString: string): void {
|
||||||
if (saveString === "") {
|
let stockMarketData: unknown;
|
||||||
StockMarket = {
|
let validate;
|
||||||
lastUpdate: 0,
|
try {
|
||||||
Orders: {},
|
stockMarketData = JSON.parse(saveString, Reviver);
|
||||||
storedCycles: 0,
|
validate = JsonSchemaValidator.StockMarket;
|
||||||
ticksUntilCycle: 0,
|
if (!validate(stockMarketData)) {
|
||||||
} as IStockMarket;
|
console.error("validate.errors:", validate.errors);
|
||||||
} else StockMarket = JSON.parse(saveString, Reviver);
|
// validate.errors is an array of objects, so we need to use JSON.stringify.
|
||||||
|
throw new Error(JSON.stringify(validate.errors));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
console.error("Invalid StockMarketSave:", saveString);
|
||||||
|
deleteStockMarket();
|
||||||
|
if (Player.hasWseAccount) {
|
||||||
|
initStockMarket();
|
||||||
|
}
|
||||||
|
const errorMessage = `Cannot load data of StockMarket. StockMarket is reset.`;
|
||||||
|
setTimeout(() => {
|
||||||
|
dialogBoxCreate(errorMessage);
|
||||||
|
}, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Typecasting here is fine because we validated the loaded data.
|
||||||
|
StockMarket = stockMarketData as IStockMarket;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteStockMarket(): void {
|
export function deleteStockMarket(): void {
|
||||||
StockMarket = {
|
StockMarket = getDefaultEmptyStockMarket();
|
||||||
lastUpdate: 0,
|
|
||||||
Orders: {},
|
|
||||||
storedCycles: 0,
|
|
||||||
ticksUntilCycle: 0,
|
|
||||||
} as IStockMarket;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initStockMarket(): void {
|
export function initStockMarket(): void {
|
||||||
|
41
test/jest/JsonSchema/AllGangsSchema.test.ts
Normal file
41
test/jest/JsonSchema/AllGangsSchema.test.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import { getDefaultAllGangs } from "../../../src/Gang/AllGangs";
|
||||||
|
import { JsonSchemaValidator } from "../../../src/JsonSchema/JsonSchemaValidator";
|
||||||
|
|
||||||
|
describe("Success", () => {
|
||||||
|
test("Default AllGangs", () => {
|
||||||
|
const defaultAllGangs = getDefaultAllGangs();
|
||||||
|
expect(JsonSchemaValidator.AllGangs(defaultAllGangs)).toStrictEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Failure", () => {
|
||||||
|
test("Do not have all gangs", () => {
|
||||||
|
const defaultAllGangs = getDefaultAllGangs() as Record<string, unknown>;
|
||||||
|
delete defaultAllGangs["Slum Snakes"];
|
||||||
|
expect(JsonSchemaValidator.AllGangs(defaultAllGangs)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
test("Have an unexpected gang", () => {
|
||||||
|
const defaultAllGangs = getDefaultAllGangs() as Record<string, unknown>;
|
||||||
|
defaultAllGangs["CyberSec"] = {
|
||||||
|
power: 1,
|
||||||
|
territory: 1 / 7,
|
||||||
|
};
|
||||||
|
expect(JsonSchemaValidator.AllGangs(defaultAllGangs)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
test("Have invalid power", () => {
|
||||||
|
const defaultAllGangs = getDefaultAllGangs() as Record<string, unknown>;
|
||||||
|
defaultAllGangs["Slum Snakes"] = {
|
||||||
|
power: "1",
|
||||||
|
territory: 1 / 7,
|
||||||
|
};
|
||||||
|
expect(JsonSchemaValidator.AllGangs(defaultAllGangs)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
test("Have invalid territory", () => {
|
||||||
|
const defaultAllGangs = getDefaultAllGangs() as Record<string, unknown>;
|
||||||
|
defaultAllGangs["Slum Snakes"] = {
|
||||||
|
power: 1,
|
||||||
|
territory: "1 / 7",
|
||||||
|
};
|
||||||
|
expect(JsonSchemaValidator.AllGangs(defaultAllGangs)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
});
|
140
test/jest/JsonSchema/StockMarketSchema.test.ts
Normal file
140
test/jest/JsonSchema/StockMarketSchema.test.ts
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
import { JsonSchemaValidator } from "../../../src/JsonSchema/JsonSchemaValidator";
|
||||||
|
import {
|
||||||
|
deleteStockMarket,
|
||||||
|
getDefaultEmptyStockMarket,
|
||||||
|
initStockMarket,
|
||||||
|
StockMarket,
|
||||||
|
} from "../../../src/StockMarket/StockMarket";
|
||||||
|
|
||||||
|
deleteStockMarket();
|
||||||
|
initStockMarket();
|
||||||
|
// Get the clone of StockMarket immediately after calling deleteStockMarket() and initStockMarket().
|
||||||
|
const defaultStockMarket = structuredClone(StockMarket);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We must call this function to get the data for testing. Do not use the module-scoped "StockMarket" from
|
||||||
|
* src/StockMarket/StockMarket. Jest tests run in parallel, so our tests may mutate that variable and result in wrong
|
||||||
|
* tests.
|
||||||
|
*/
|
||||||
|
function getCloneOfDefaultStockMarket(): Record<string, unknown> {
|
||||||
|
return structuredClone(defaultStockMarket);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCloneOfSampleStock() {
|
||||||
|
return {
|
||||||
|
name: "ECorp",
|
||||||
|
symbol: "ECP",
|
||||||
|
price: 24618.907733048673,
|
||||||
|
lastPrice: 24702.20549043557,
|
||||||
|
playerShares: 2,
|
||||||
|
playerAvgPx: 19893.251484918932,
|
||||||
|
playerShortShares: 0,
|
||||||
|
playerAvgShortPx: 0,
|
||||||
|
mv: 0.44,
|
||||||
|
b: true,
|
||||||
|
otlkMag: 17.783525574804138,
|
||||||
|
otlkMagForecast: 68.11871382128285,
|
||||||
|
cap: 148683699,
|
||||||
|
spreadPerc: 0.5,
|
||||||
|
shareTxForMovement: 76967,
|
||||||
|
shareTxUntilMovement: 76967,
|
||||||
|
totalShares: 140600000,
|
||||||
|
maxShares: 28100000,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCloneOfSampleOrders() {
|
||||||
|
return {
|
||||||
|
ECP: [
|
||||||
|
{
|
||||||
|
stockSymbol: "ECP",
|
||||||
|
shares: 1,
|
||||||
|
price: 1000,
|
||||||
|
type: "Limit Buy Order",
|
||||||
|
pos: "L",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type SampleOrders = ReturnType<typeof getCloneOfSampleOrders>;
|
||||||
|
|
||||||
|
describe("Success", () => {
|
||||||
|
test("Default empty StockMarket", () => {
|
||||||
|
expect(JsonSchemaValidator.StockMarket(getDefaultEmptyStockMarket())).toStrictEqual(true);
|
||||||
|
});
|
||||||
|
test("Default StockMarket", () => {
|
||||||
|
expect(JsonSchemaValidator.StockMarket(getCloneOfDefaultStockMarket())).toStrictEqual(true);
|
||||||
|
});
|
||||||
|
test("StockMarket with Orders", () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
stockMarket.Orders = getCloneOfSampleOrders();
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Failure", () => {
|
||||||
|
test("Have unexpected property", () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
stockMarket.test = "";
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Do not have lastUpdate property", () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
delete stockMarket.lastUpdate;
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Invalid stock", () => {
|
||||||
|
test("Have invalid type of stock", () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
stockMarket.ECorp = [];
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
const sampleStock = getCloneOfSampleStock();
|
||||||
|
for (const [key, value] of Object.entries(sampleStock)) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
test(`Have invalid ${key}`, () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
stockMarket.ECorp = getCloneOfSampleStock();
|
||||||
|
(stockMarket.ECorp as { [_: string]: unknown })[key] = "test";
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Invalid Orders", () => {
|
||||||
|
test("Have invalid type of Orders", () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
stockMarket.Orders = [];
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
test("Have invalid Order: Invalid order type", () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
stockMarket.Orders = getCloneOfSampleOrders();
|
||||||
|
(stockMarket.Orders as SampleOrders).ECP[0].type = "Limit Buy Order1";
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
test("Have invalid Order: Invalid position type", () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
stockMarket.Orders = getCloneOfSampleOrders();
|
||||||
|
(stockMarket.Orders as SampleOrders).ECP[0].pos = "L1";
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
test("Have invalid Order: Invalid shares", () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
stockMarket.Orders = getCloneOfSampleOrders();
|
||||||
|
((stockMarket.Orders as SampleOrders).ECP[0].shares as unknown) = "1";
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
test("Have invalid Order: Invalid price", () => {
|
||||||
|
const stockMarket = getCloneOfDefaultStockMarket();
|
||||||
|
stockMarket.Orders = getCloneOfSampleOrders();
|
||||||
|
((stockMarket.Orders as SampleOrders).ECP[0].price as unknown) = "1000";
|
||||||
|
expect(JsonSchemaValidator.StockMarket(stockMarket)).toStrictEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user