diff --git a/.eslintignore b/.eslintignore index f0da1ec30..7cb0ed0e8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,3 +2,7 @@ node_modules/ doc/build/ dist/ tests/*.bundle.* +src/ThirdParty/* +src/ScriptEditor/CodeMirrorNetscriptMode.js +src/ScriptEditor/CodeMirrorNetscriptLint.js +src/JSInterpreter.js \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index 507680fb0..2812ebcbf 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -76,7 +76,7 @@ module.exports = { "imports": "always-multiline", "exports": "always-multiline", "functions": "always-multiline", - } + }, ], "comma-spacing": [ "off", @@ -102,14 +102,14 @@ module.exports = { "error", ], "curly": [ - "off" + "off", ], "default-case": [ - "off" + "off", ], "dot-location": [ "error", - "property" + "property", ], "dot-notation": [ "off", @@ -310,104 +310,104 @@ module.exports = { "error", ], "no-div-regex": [ - "error" + "error", ], "no-dupe-args": [ - "error" + "error", ], "no-dupe-class-members": [ - "error" + "error", ], "no-dupe-keys": [ - "error" + "error", ], "no-duplicate-case": [ - "error" + "error", ], "no-duplicate-imports": [ "error", { - "includeExports": true - } + "includeExports": true, + }, ], "no-else-return": [ - "off" + "off", ], "no-empty": [ "off", { - "allowEmptyCatch": false - } + "allowEmptyCatch": false, + }, ], "no-empty-character-class": [ - "error" + "error", ], "no-empty-function": [ - "off" + "off", ], "no-empty-pattern": [ - "error" + "error", ], "no-eq-null": [ - "off" + "off", ], "no-ex-assign": [ - "off" + "off", ], "no-extra-boolean-cast": [ - "error" + "error", ], "no-extra-parens": [ - "off" + "off", ], "no-extra-semi": [ - "off" + "off", ], "no-eval": [ - "off" + "off", ], "no-extend-native": [ - "off" + "off", ], "no-extra-bind": [ - "error" + "error", ], "no-extra-label": [ - "error" + "error", ], "no-fallthrough": [ - "off" + "off", ], "no-floating-decimal": [ - "off" + "off", ], "no-func-assign": [ - "error" + "error", ], "no-global-assign": [ - "error" + "error", ], "no-implicit-coercion": [ - "off" + "off", ], "no-implicit-globals": [ - "error" + "error", ], "no-implied-eval": [ - "error" + "error", ], "no-inline-comments": [ - "off" + "off", ], "no-inner-declarations": [ "off", - "both" + "both", ], "no-invalid-regexp": [ - "error" + "error", ], "no-invalid-this": [ - "off" + "off", ], "no-irregular-whitespace": [ "error", @@ -415,451 +415,461 @@ module.exports = { "skipStrings": false, "skipComments": false, "skipRegExps": false, - "skipTemplates": false - } + "skipTemplates": false, + }, ], "no-iterator": [ - "error" + "error", ], "no-label-var": [ - "error" + "error", ], "no-labels": [ - "off" + "off", ], "no-lone-blocks": [ - "error" + "error", ], "no-lonely-if": [ - "off" + "off", ], "no-loop-func": [ - "off" + "off", ], "no-magic-numbers": [ - "off" + "off", ], "no-mixed-operators": [ - "off" + "off", ], "no-mixed-requires": [ - "error" + "error", ], "no-mixed-spaces-and-tabs": [ - "off" + "off", ], "no-multi-assign": [ - "off" + "off", ], "no-multi-spaces": [ - "off" + "off", ], "no-multi-str": [ - "error" + "error", ], "no-multiple-empty-lines": [ "off", { - "max": 1 - } + "max": 1, + }, ], "no-native-reassign": [ - "error" + "error", ], "no-negated-condition": [ - "off" + "off", ], "no-negated-in-lhs": [ - "error" + "error", ], "no-nested-ternary": [ - "off" + "off", ], "no-new": [ - "error" + "error", ], "no-new-func": [ - "error" + "error", ], "no-new-object": [ - "error" + "error", ], "no-new-require": [ - "error" + "error", ], "no-new-symbol": [ - "error" + "error", ], "no-new-wrappers": [ - "error" + "error", ], "no-octal": [ - "error" + "error", ], "no-octal-escape": [ - "error" + "error", ], "no-obj-calls": [ - "error" + "error", ], "no-param-reassign": [ - "off" + "off", ], "no-path-concat": [ - "error" + "error", ], "no-plusplus": [ - "off" + "off", ], "no-process-env": [ - "off" + "off", ], "no-process-exit": [ - "error" + "error", ], "no-proto": [ - "error" + "error", ], "no-prototype-builtins": [ - "off" + "off", ], "no-redeclare": [ - "off" + "off", ], "no-regex-spaces": [ - "error" + "error", ], "no-restricted-globals": [ - "error" + "error", ], "no-restricted-imports": [ - "error" + "error", ], "no-restricted-modules": [ - "error" + "error", ], "no-restricted-properties": [ "off", { "object": "console", "property": "log", - "message": "'log' is too general, use an appropriate level when logging." - } + "message": "'log' is too general, use an appropriate level when logging.", + }, ], "no-restricted-syntax": [ - "error" + "error", ], "no-return-assign": [ - "off" + "off", ], "no-return-await": [ - "error" + "error", ], "no-script-url": [ - "error" + "error", ], "no-self-assign": [ "error", { - "props": false - } + "props": false, + }, ], "no-self-compare": [ - "error" + "error", ], "no-sequences": [ - "error" + "error", ], "no-shadow": [ - "off" + "off", ], "no-shadow-restricted-names": [ - "error" + "error", ], "no-spaced-func": [ - "off" + "off", ], "no-sparse-arrays": [ - "error" + "error", ], "no-sync": [ - "error" + "error", ], "no-tabs": [ - "off" + "off", ], "no-template-curly-in-string": [ - "error" + "error", ], "no-ternary": [ - "off" + "off", ], "no-this-before-super": [ - "off" + "off", ], "no-throw-literal": [ - "error" + "error", ], "no-trailing-spaces": [ - "off" + "off", ], "no-undef": [ - "off" + "off", ], "no-undef-init": [ - "error" + "error", ], "no-undefined": [ - "off" + "off", ], "no-underscore-dangle": [ - "off" + "off", ], "no-unexpected-multiline": [ - "error" + "error", ], "no-unmodified-loop-condition": [ - "error" + "error", ], "no-unneeded-ternary": [ - "off" + "off", ], "no-unreachable": [ - "off" + "off", ], "no-unsafe-finally": [ - "error" + "error", ], "no-unsafe-negation": [ - "error" + "error", ], "no-unused-expressions": [ - "off" + "off", ], "no-unused-labels": [ - "error" + "error", ], "no-unused-vars": [ - "off" + "off", ], "no-use-before-define": [ - "off" + "off", ], "no-useless-call": [ - "off" + "off", ], "no-useless-computed-key": [ - "error" + "error", ], "no-useless-concat": [ - "off" + "off", ], "no-useless-constructor": [ - "error" + "error", ], "no-useless-escape": [ - "off" + "off", ], "no-useless-rename": [ "error", { "ignoreDestructuring": false, "ignoreExport": false, - "ignoreImport": false - } + "ignoreImport": false, + }, ], "no-useless-return": [ - "off" + "off", ], "no-var": [ - "off" + "off", ], "no-void": [ - "off" + "off", ], "no-warning-comments": [ - "off" + "off", ], "no-whitespace-before-property": [ - "error" + "error", ], "no-with": [ - "error" + "error", ], "nonblock-statement-body-position": [ "off", - "below" + "below", ], "object-curly-newline": [ - "off" + "off", ], "object-curly-spacing": [ - "off" + "off", ], "object-property-newline": [ - "off" + "off", ], "object-shorthand": [ - "off" + "off", ], "one-var": [ - "off" + "off", ], "one-var-declaration-per-line": [ - "off" + "off", ], "operator-assignment": [ - "off" + "off", ], "operator-linebreak": [ "off", - "none" + "none", ], "padded-blocks": [ - "off" + "off", ], "padding-line-between-statements": [ - "error" + "error", ], "prefer-arrow-callback": [ - "off" + "off", ], "prefer-const": [ - "off" + "off", ], "prefer-destructuring": [ - "off" + "off", ], "prefer-numeric-literals": [ - "error" + "error", ], "prefer-promise-reject-errors": [ - "off" + "off", ], "prefer-reflect": [ - "off" + "off", ], "prefer-rest-params": [ - "off" + "off", ], "prefer-spread": [ - "off" + "off", ], "prefer-template": [ - "off" + "off", ], "quote-props": [ - "off" + "off", ], "quotes": [ - "off" + "off", ], "radix": [ "off", - "as-needed" + "as-needed", ], "require-await": [ - "off" + "off", ], "require-jsdoc": [ - "off" + "off", ], "require-yield": [ - "error" + "error", ], "rest-spread-spacing": [ "error", - "never" + "never", ], "semi": [ - "off" + "off", ], "semi-spacing": [ - "off" + "off", ], "semi-style": [ "error", - "last" + "last", ], "sort-imports": [ - "off" + "off", ], "sort-keys": [ - "off" + "off", ], "sort-vars": [ - "off" + "off", ], "space-before-blocks": [ - "off" + "off", ], "space-before-function-paren": [ - "off" + "off", ], "space-in-parens": [ - "off" + "off", ], "space-infix-ops": [ - "off" + "off", ], "space-unary-ops": [ - "off" + "off", ], "spaced-comment": [ - "off" + "off", ], "strict": [ - "off" + "off", ], "switch-colon-spacing": [ "error", { "after": true, - "before": false - } + "before": false, + }, ], "symbol-description": [ - "error" + "error", ], "template-curly-spacing": [ - "error" + "error", ], "template-tag-spacing": [ - "error" + "error", ], "unicode-bom": [ "error", - "never" + "never", ], "use-isnan": [ - "error" + "error", ], "valid-jsdoc": [ - "off" + "off", ], "valid-typeof": [ - "error" + "error", ], "vars-on-top": [ - "off" + "off", ], "wrap-iife": [ "error", - "any" + "any", ], "wrap-regex": [ - "off" + "off", ], "yield-star-spacing": [ "error", - "before" + "before", ], "yoda": [ "error", - "never" - ] + "never", + ], + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/explicit-function-return-type": "off", }, "overrides": [ + { + // enable the rule specifically for TypeScript files + "files": ["*.ts", "*.tsx"], + "rules": { + "@typescript-eslint/explicit-function-return-type": ["error"], + "@typescript-eslint/explicit-module-boundary-types": ["error"], + }, + }, { // TypeScript configuration "files": [ "**/*.ts", "**/*.tsx" ], @@ -888,7 +898,7 @@ module.exports = { "singleline": { "delimiter": "semi", "requireLast": false, - } + }, }], "@typescript-eslint/member-ordering": ["error", { "default": [ @@ -900,11 +910,11 @@ module.exports = { "instance-method", "abstract-method", "static-method", - ] + ], }], "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-use-before-define": "off", - } - } - ] + }, + }, + ], }; \ No newline at end of file diff --git a/css/casino.scss b/css/casino.scss index d4bc6be6f..c7cd6280a 100644 --- a/css/casino.scss +++ b/css/casino.scss @@ -1,24 +1,24 @@ .casino-card { - padding: 10px; - border: solid 1px #808080; - background-color: white; - display: inline-block; - border-radius: 10px; - font-size: 14pt; - text-align: center; - margin: 3px; - font-weight: bold; + padding: 10px; + border: solid 1px #808080; + background-color: white; + display: inline-block; + border-radius: 10px; + font-size: 14pt; + text-align: center; + margin: 3px; + font-weight: bold; } .casino-card .value { - font-size:15pt; - font-family: sans-serif; + font-size:15pt; + font-family: sans-serif; } .casino-card.red { - color: red; + color: red; } .casino-card.black { - color: black; -} \ No newline at end of file + color: black; +} diff --git a/css/characteroverview.scss b/css/characteroverview.scss index d23a8e587..ea48f9085 100644 --- a/css/characteroverview.scss +++ b/css/characteroverview.scss @@ -43,9 +43,9 @@ background-color: #444; } - .character-stat-cell { - text-align: right; - } +.character-stat-cell { + text-align: right; +} #character-hack-wrapper td, #character-agi-wrapper td { diff --git a/css/codemirror-overrides.scss b/css/codemirror-overrides.scss index 0c286d53a..193e0a3f1 100644 --- a/css/codemirror-overrides.scss +++ b/css/codemirror-overrides.scss @@ -6,7 +6,7 @@ #codemirror-form-wrapper { height: 80%; - margin: 10px 0px 0px 6px; + margin: 10px 0 0 6px; } .CodeMirror { @@ -22,11 +22,11 @@ * Highlight matches */ .cm-matchhighlight { - background-color: #8F908A; + background-color: #8f908a; } .CodeMirror-selection-highlight-scrollbar { - background-color: #8F908A; + background-color: #8f908a; } /** @@ -35,7 +35,7 @@ .cm-whitespace::before { position: absolute; pointer-events: none; - color: #404F7D; + color: #404f7d; } /** diff --git a/css/dev-menu.css b/css/dev-menu.css index 21a93e78b..10e7c058c 100644 --- a/css/dev-menu.css +++ b/css/dev-menu.css @@ -1,36 +1,36 @@ .add-exp-button { - margin-right: 0px; + margin-right: 0; } .remove-exp-button { - margin-left:0px; + margin-left:0; } .exp-input { - margin-right: 0px; - margin-left:0px; + margin-right: 0; + margin-left:0; - margin-top: 5px; - margin-bottom: 5px; + margin-top: 5px; + margin-bottom: 5px; - padding: 2px 5px; + padding: 2px 5px; } .text-center { - margin: auto; - text-align: center; - vertical-align: middle; + margin: auto; + text-align: center; + vertical-align: middle; } .touch-right { - margin-right: 0px; + margin-right: 0; } .touch-left { - margin-left: 0px; + margin-left: 0; } .touch-sides { - margin-left: 0px; - margin-right: 0px; -} \ No newline at end of file + margin-left: 0; + margin-right: 0; +} diff --git a/css/grid.min.css b/css/grid.min.css index d617299c5..c32112cbb 100644 --- a/css/grid.min.css +++ b/css/grid.min.css @@ -3,4 +3,4 @@ * Copyright 2011-2018 The Bootstrap Authors * Copyright 2011-2018 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */@-ms-viewport{width:device-width}html{-webkit-box-sizing:border-box;box-sizing:border-box;-ms-overflow-style:scrollbar}*,*::before,*::after{-webkit-box-sizing:inherit;box-sizing:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container{max-width:540px}}@media (min-width: 768px){.container{max-width:720px}}@media (min-width: 992px){.container{max-width:960px}}@media (min-width: 1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*="col-"]{padding-right:0;padding-left:0}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col,.col-auto,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm,.col-sm-auto,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md,.col-md-auto,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg,.col-lg-auto,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}@media (min-width: 576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-sm-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-sm-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-sm-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-sm-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-sm-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-sm-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-sm-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}}@media (min-width: 768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-md-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-md-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-md-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-md-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-md-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-md-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-md-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}}@media (min-width: 992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-lg-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-lg-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-lg-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-lg-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-lg-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-lg-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-lg-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}}@media (min-width: 1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-xl-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-xl-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-xl-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-xl-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-xl-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-xl-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-xl-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}@media (min-width: 576px){.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-sm-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 768px){.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-md-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 992px){.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-lg-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 1200px){.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-xl-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-print-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}.flex-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}@media (min-width: 576px){.flex-sm-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-sm-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-sm-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-sm-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-sm-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-sm-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-sm-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-sm-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-sm-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-sm-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-sm-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-sm-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-sm-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-sm-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-sm-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-sm-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-sm-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-sm-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-sm-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-sm-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-sm-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-sm-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-sm-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-sm-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-sm-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-sm-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-sm-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-sm-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-sm-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-sm-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-sm-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-sm-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-sm-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 768px){.flex-md-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-md-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-md-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-md-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-md-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-md-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-md-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-md-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-md-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-md-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-md-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-md-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-md-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-md-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-md-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-md-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-md-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-md-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-md-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-md-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-md-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-md-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-md-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-md-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-md-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-md-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-md-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-md-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-md-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-md-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-md-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-md-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-md-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 992px){.flex-lg-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-lg-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-lg-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-lg-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-lg-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-lg-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-lg-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-lg-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-lg-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-lg-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-lg-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-lg-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-lg-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-lg-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-lg-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-lg-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-lg-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-lg-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-lg-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-lg-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-lg-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-lg-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-lg-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-lg-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-lg-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-lg-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-lg-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-lg-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-lg-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-lg-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-lg-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-lg-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-lg-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 1200px){.flex-xl-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-xl-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-xl-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-xl-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-xl-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-xl-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-xl-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-xl-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-xl-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-xl-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-xl-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-xl-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-xl-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-xl-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-xl-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-xl-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-xl-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-xl-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-xl-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-xl-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-xl-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-xl-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-xl-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-xl-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-xl-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-xl-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-xl-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-xl-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-xl-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-xl-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-xl-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-xl-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-xl-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mw-100{max-width:100% !important}.mh-100{max-height:100% !important}.m-0{margin:0 !important}.mt-0,.my-0{margin-top:0 !important}.mr-0,.mx-0{margin-right:0 !important}.mb-0,.my-0{margin-bottom:0 !important}.ml-0,.mx-0{margin-left:0 !important}.m-1{margin:.25rem !important}.mt-1,.my-1{margin-top:.25rem !important}.mr-1,.mx-1{margin-right:.25rem !important}.mb-1,.my-1{margin-bottom:.25rem !important}.ml-1,.mx-1{margin-left:.25rem !important}.m-2{margin:.5rem !important}.mt-2,.my-2{margin-top:.5rem !important}.mr-2,.mx-2{margin-right:.5rem !important}.mb-2,.my-2{margin-bottom:.5rem !important}.ml-2,.mx-2{margin-left:.5rem !important}.m-3{margin:1rem !important}.mt-3,.my-3{margin-top:1rem !important}.mr-3,.mx-3{margin-right:1rem !important}.mb-3,.my-3{margin-bottom:1rem !important}.ml-3,.mx-3{margin-left:1rem !important}.m-4{margin:1.5rem !important}.mt-4,.my-4{margin-top:1.5rem !important}.mr-4,.mx-4{margin-right:1.5rem !important}.mb-4,.my-4{margin-bottom:1.5rem !important}.ml-4,.mx-4{margin-left:1.5rem !important}.m-5{margin:3rem !important}.mt-5,.my-5{margin-top:3rem !important}.mr-5,.mx-5{margin-right:3rem !important}.mb-5,.my-5{margin-bottom:3rem !important}.ml-5,.mx-5{margin-left:3rem !important}.p-0{padding:0 !important}.pt-0,.py-0{padding-top:0 !important}.pr-0,.px-0{padding-right:0 !important}.pb-0,.py-0{padding-bottom:0 !important}.pl-0,.px-0{padding-left:0 !important}.p-1{padding:.25rem !important}.pt-1,.py-1{padding-top:.25rem !important}.pr-1,.px-1{padding-right:.25rem !important}.pb-1,.py-1{padding-bottom:.25rem !important}.pl-1,.px-1{padding-left:.25rem !important}.p-2{padding:.5rem !important}.pt-2,.py-2{padding-top:.5rem !important}.pr-2,.px-2{padding-right:.5rem !important}.pb-2,.py-2{padding-bottom:.5rem !important}.pl-2,.px-2{padding-left:.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-auto{margin:auto !important}.mt-auto,.my-auto{margin-top:auto !important}.mr-auto,.mx-auto{margin-right:auto !important}.mb-auto,.my-auto{margin-bottom:auto !important}.ml-auto,.mx-auto{margin-left:auto !important}@media (min-width: 576px){.m-sm-0{margin:0 !important}.mt-sm-0,.my-sm-0{margin-top:0 !important}.mr-sm-0,.mx-sm-0{margin-right:0 !important}.mb-sm-0,.my-sm-0{margin-bottom:0 !important}.ml-sm-0,.mx-sm-0{margin-left:0 !important}.m-sm-1{margin:.25rem !important}.mt-sm-1,.my-sm-1{margin-top:.25rem !important}.mr-sm-1,.mx-sm-1{margin-right:.25rem !important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem !important}.ml-sm-1,.mx-sm-1{margin-left:.25rem !important}.m-sm-2{margin:.5rem !important}.mt-sm-2,.my-sm-2{margin-top:.5rem !important}.mr-sm-2,.mx-sm-2{margin-right:.5rem !important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem !important}.ml-sm-2,.mx-sm-2{margin-left:.5rem !important}.m-sm-3{margin:1rem !important}.mt-sm-3,.my-sm-3{margin-top:1rem !important}.mr-sm-3,.mx-sm-3{margin-right:1rem !important}.mb-sm-3,.my-sm-3{margin-bottom:1rem !important}.ml-sm-3,.mx-sm-3{margin-left:1rem !important}.m-sm-4{margin:1.5rem !important}.mt-sm-4,.my-sm-4{margin-top:1.5rem !important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem !important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem !important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem !important}.m-sm-5{margin:3rem !important}.mt-sm-5,.my-sm-5{margin-top:3rem !important}.mr-sm-5,.mx-sm-5{margin-right:3rem !important}.mb-sm-5,.my-sm-5{margin-bottom:3rem !important}.ml-sm-5,.mx-sm-5{margin-left:3rem !important}.p-sm-0{padding:0 !important}.pt-sm-0,.py-sm-0{padding-top:0 !important}.pr-sm-0,.px-sm-0{padding-right:0 !important}.pb-sm-0,.py-sm-0{padding-bottom:0 !important}.pl-sm-0,.px-sm-0{padding-left:0 !important}.p-sm-1{padding:.25rem !important}.pt-sm-1,.py-sm-1{padding-top:.25rem !important}.pr-sm-1,.px-sm-1{padding-right:.25rem !important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem !important}.pl-sm-1,.px-sm-1{padding-left:.25rem !important}.p-sm-2{padding:.5rem !important}.pt-sm-2,.py-sm-2{padding-top:.5rem !important}.pr-sm-2,.px-sm-2{padding-right:.5rem !important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem !important}.pl-sm-2,.px-sm-2{padding-left:.5rem !important}.p-sm-3{padding:1rem !important}.pt-sm-3,.py-sm-3{padding-top:1rem !important}.pr-sm-3,.px-sm-3{padding-right:1rem !important}.pb-sm-3,.py-sm-3{padding-bottom:1rem !important}.pl-sm-3,.px-sm-3{padding-left:1rem !important}.p-sm-4{padding:1.5rem !important}.pt-sm-4,.py-sm-4{padding-top:1.5rem !important}.pr-sm-4,.px-sm-4{padding-right:1.5rem !important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem !important}.pl-sm-4,.px-sm-4{padding-left:1.5rem !important}.p-sm-5{padding:3rem !important}.pt-sm-5,.py-sm-5{padding-top:3rem !important}.pr-sm-5,.px-sm-5{padding-right:3rem !important}.pb-sm-5,.py-sm-5{padding-bottom:3rem !important}.pl-sm-5,.px-sm-5{padding-left:3rem !important}.m-sm-auto{margin:auto !important}.mt-sm-auto,.my-sm-auto{margin-top:auto !important}.mr-sm-auto,.mx-sm-auto{margin-right:auto !important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto !important}.ml-sm-auto,.mx-sm-auto{margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0,.my-md-0{margin-top:0 !important}.mr-md-0,.mx-md-0{margin-right:0 !important}.mb-md-0,.my-md-0{margin-bottom:0 !important}.ml-md-0,.mx-md-0{margin-left:0 !important}.m-md-1{margin:.25rem !important}.mt-md-1,.my-md-1{margin-top:.25rem !important}.mr-md-1,.mx-md-1{margin-right:.25rem !important}.mb-md-1,.my-md-1{margin-bottom:.25rem !important}.ml-md-1,.mx-md-1{margin-left:.25rem !important}.m-md-2{margin:.5rem !important}.mt-md-2,.my-md-2{margin-top:.5rem !important}.mr-md-2,.mx-md-2{margin-right:.5rem !important}.mb-md-2,.my-md-2{margin-bottom:.5rem !important}.ml-md-2,.mx-md-2{margin-left:.5rem !important}.m-md-3{margin:1rem !important}.mt-md-3,.my-md-3{margin-top:1rem !important}.mr-md-3,.mx-md-3{margin-right:1rem !important}.mb-md-3,.my-md-3{margin-bottom:1rem !important}.ml-md-3,.mx-md-3{margin-left:1rem !important}.m-md-4{margin:1.5rem !important}.mt-md-4,.my-md-4{margin-top:1.5rem !important}.mr-md-4,.mx-md-4{margin-right:1.5rem !important}.mb-md-4,.my-md-4{margin-bottom:1.5rem !important}.ml-md-4,.mx-md-4{margin-left:1.5rem !important}.m-md-5{margin:3rem !important}.mt-md-5,.my-md-5{margin-top:3rem !important}.mr-md-5,.mx-md-5{margin-right:3rem !important}.mb-md-5,.my-md-5{margin-bottom:3rem !important}.ml-md-5,.mx-md-5{margin-left:3rem !important}.p-md-0{padding:0 !important}.pt-md-0,.py-md-0{padding-top:0 !important}.pr-md-0,.px-md-0{padding-right:0 !important}.pb-md-0,.py-md-0{padding-bottom:0 !important}.pl-md-0,.px-md-0{padding-left:0 !important}.p-md-1{padding:.25rem !important}.pt-md-1,.py-md-1{padding-top:.25rem !important}.pr-md-1,.px-md-1{padding-right:.25rem !important}.pb-md-1,.py-md-1{padding-bottom:.25rem !important}.pl-md-1,.px-md-1{padding-left:.25rem !important}.p-md-2{padding:.5rem !important}.pt-md-2,.py-md-2{padding-top:.5rem !important}.pr-md-2,.px-md-2{padding-right:.5rem !important}.pb-md-2,.py-md-2{padding-bottom:.5rem !important}.pl-md-2,.px-md-2{padding-left:.5rem !important}.p-md-3{padding:1rem !important}.pt-md-3,.py-md-3{padding-top:1rem !important}.pr-md-3,.px-md-3{padding-right:1rem !important}.pb-md-3,.py-md-3{padding-bottom:1rem !important}.pl-md-3,.px-md-3{padding-left:1rem !important}.p-md-4{padding:1.5rem !important}.pt-md-4,.py-md-4{padding-top:1.5rem !important}.pr-md-4,.px-md-4{padding-right:1.5rem !important}.pb-md-4,.py-md-4{padding-bottom:1.5rem !important}.pl-md-4,.px-md-4{padding-left:1.5rem !important}.p-md-5{padding:3rem !important}.pt-md-5,.py-md-5{padding-top:3rem !important}.pr-md-5,.px-md-5{padding-right:3rem !important}.pb-md-5,.py-md-5{padding-bottom:3rem !important}.pl-md-5,.px-md-5{padding-left:3rem !important}.m-md-auto{margin:auto !important}.mt-md-auto,.my-md-auto{margin-top:auto !important}.mr-md-auto,.mx-md-auto{margin-right:auto !important}.mb-md-auto,.my-md-auto{margin-bottom:auto !important}.ml-md-auto,.mx-md-auto{margin-left:auto !important}}@media (min-width: 992px){.m-lg-0{margin:0 !important}.mt-lg-0,.my-lg-0{margin-top:0 !important}.mr-lg-0,.mx-lg-0{margin-right:0 !important}.mb-lg-0,.my-lg-0{margin-bottom:0 !important}.ml-lg-0,.mx-lg-0{margin-left:0 !important}.m-lg-1{margin:.25rem !important}.mt-lg-1,.my-lg-1{margin-top:.25rem !important}.mr-lg-1,.mx-lg-1{margin-right:.25rem !important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem !important}.ml-lg-1,.mx-lg-1{margin-left:.25rem !important}.m-lg-2{margin:.5rem !important}.mt-lg-2,.my-lg-2{margin-top:.5rem !important}.mr-lg-2,.mx-lg-2{margin-right:.5rem !important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem !important}.ml-lg-2,.mx-lg-2{margin-left:.5rem !important}.m-lg-3{margin:1rem !important}.mt-lg-3,.my-lg-3{margin-top:1rem !important}.mr-lg-3,.mx-lg-3{margin-right:1rem !important}.mb-lg-3,.my-lg-3{margin-bottom:1rem !important}.ml-lg-3,.mx-lg-3{margin-left:1rem !important}.m-lg-4{margin:1.5rem !important}.mt-lg-4,.my-lg-4{margin-top:1.5rem !important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem !important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem !important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem !important}.m-lg-5{margin:3rem !important}.mt-lg-5,.my-lg-5{margin-top:3rem !important}.mr-lg-5,.mx-lg-5{margin-right:3rem !important}.mb-lg-5,.my-lg-5{margin-bottom:3rem !important}.ml-lg-5,.mx-lg-5{margin-left:3rem !important}.p-lg-0{padding:0 !important}.pt-lg-0,.py-lg-0{padding-top:0 !important}.pr-lg-0,.px-lg-0{padding-right:0 !important}.pb-lg-0,.py-lg-0{padding-bottom:0 !important}.pl-lg-0,.px-lg-0{padding-left:0 !important}.p-lg-1{padding:.25rem !important}.pt-lg-1,.py-lg-1{padding-top:.25rem !important}.pr-lg-1,.px-lg-1{padding-right:.25rem !important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem !important}.pl-lg-1,.px-lg-1{padding-left:.25rem !important}.p-lg-2{padding:.5rem !important}.pt-lg-2,.py-lg-2{padding-top:.5rem !important}.pr-lg-2,.px-lg-2{padding-right:.5rem !important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem !important}.pl-lg-2,.px-lg-2{padding-left:.5rem !important}.p-lg-3{padding:1rem !important}.pt-lg-3,.py-lg-3{padding-top:1rem !important}.pr-lg-3,.px-lg-3{padding-right:1rem !important}.pb-lg-3,.py-lg-3{padding-bottom:1rem !important}.pl-lg-3,.px-lg-3{padding-left:1rem !important}.p-lg-4{padding:1.5rem !important}.pt-lg-4,.py-lg-4{padding-top:1.5rem !important}.pr-lg-4,.px-lg-4{padding-right:1.5rem !important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem !important}.pl-lg-4,.px-lg-4{padding-left:1.5rem !important}.p-lg-5{padding:3rem !important}.pt-lg-5,.py-lg-5{padding-top:3rem !important}.pr-lg-5,.px-lg-5{padding-right:3rem !important}.pb-lg-5,.py-lg-5{padding-bottom:3rem !important}.pl-lg-5,.px-lg-5{padding-left:3rem !important}.m-lg-auto{margin:auto !important}.mt-lg-auto,.my-lg-auto{margin-top:auto !important}.mr-lg-auto,.mx-lg-auto{margin-right:auto !important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto !important}.ml-lg-auto,.mx-lg-auto{margin-left:auto !important}}@media (min-width: 1200px){.m-xl-0{margin:0 !important}.mt-xl-0,.my-xl-0{margin-top:0 !important}.mr-xl-0,.mx-xl-0{margin-right:0 !important}.mb-xl-0,.my-xl-0{margin-bottom:0 !important}.ml-xl-0,.mx-xl-0{margin-left:0 !important}.m-xl-1{margin:.25rem !important}.mt-xl-1,.my-xl-1{margin-top:.25rem !important}.mr-xl-1,.mx-xl-1{margin-right:.25rem !important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem !important}.ml-xl-1,.mx-xl-1{margin-left:.25rem !important}.m-xl-2{margin:.5rem !important}.mt-xl-2,.my-xl-2{margin-top:.5rem !important}.mr-xl-2,.mx-xl-2{margin-right:.5rem !important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem !important}.ml-xl-2,.mx-xl-2{margin-left:.5rem !important}.m-xl-3{margin:1rem !important}.mt-xl-3,.my-xl-3{margin-top:1rem !important}.mr-xl-3,.mx-xl-3{margin-right:1rem !important}.mb-xl-3,.my-xl-3{margin-bottom:1rem !important}.ml-xl-3,.mx-xl-3{margin-left:1rem !important}.m-xl-4{margin:1.5rem !important}.mt-xl-4,.my-xl-4{margin-top:1.5rem !important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem !important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem !important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem !important}.m-xl-5{margin:3rem !important}.mt-xl-5,.my-xl-5{margin-top:3rem !important}.mr-xl-5,.mx-xl-5{margin-right:3rem !important}.mb-xl-5,.my-xl-5{margin-bottom:3rem !important}.ml-xl-5,.mx-xl-5{margin-left:3rem !important}.p-xl-0{padding:0 !important}.pt-xl-0,.py-xl-0{padding-top:0 !important}.pr-xl-0,.px-xl-0{padding-right:0 !important}.pb-xl-0,.py-xl-0{padding-bottom:0 !important}.pl-xl-0,.px-xl-0{padding-left:0 !important}.p-xl-1{padding:.25rem !important}.pt-xl-1,.py-xl-1{padding-top:.25rem !important}.pr-xl-1,.px-xl-1{padding-right:.25rem !important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem !important}.pl-xl-1,.px-xl-1{padding-left:.25rem !important}.p-xl-2{padding:.5rem !important}.pt-xl-2,.py-xl-2{padding-top:.5rem !important}.pr-xl-2,.px-xl-2{padding-right:.5rem !important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem !important}.pl-xl-2,.px-xl-2{padding-left:.5rem !important}.p-xl-3{padding:1rem !important}.pt-xl-3,.py-xl-3{padding-top:1rem !important}.pr-xl-3,.px-xl-3{padding-right:1rem !important}.pb-xl-3,.py-xl-3{padding-bottom:1rem !important}.pl-xl-3,.px-xl-3{padding-left:1rem !important}.p-xl-4{padding:1.5rem !important}.pt-xl-4,.py-xl-4{padding-top:1.5rem !important}.pr-xl-4,.px-xl-4{padding-right:1.5rem !important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem !important}.pl-xl-4,.px-xl-4{padding-left:1.5rem !important}.p-xl-5{padding:3rem !important}.pt-xl-5,.py-xl-5{padding-top:3rem !important}.pr-xl-5,.px-xl-5{padding-right:3rem !important}.pb-xl-5,.py-xl-5{padding-bottom:3rem !important}.pl-xl-5,.px-xl-5{padding-left:3rem !important}.m-xl-auto{margin:auto !important}.mt-xl-auto,.my-xl-auto{margin-top:auto !important}.mr-xl-auto,.mx-xl-auto{margin-right:auto !important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto !important}.ml-xl-auto,.mx-xl-auto{margin-left:auto !important}}.visible{visibility:visible !important}.invisible{visibility:hidden !important} \ No newline at end of file + */@-ms-viewport{width:device-width}html{-webkit-box-sizing:border-box;box-sizing:border-box;-ms-overflow-style:scrollbar}*,*::before,*::after{-webkit-box-sizing:inherit;box-sizing:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 576px){.container{max-width:540px}}@media (min-width: 768px){.container{max-width:720px}}@media (min-width: 992px){.container{max-width:960px}}@media (min-width: 1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*="col-"]{padding-right:0;padding-left:0}.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col,.col-auto,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm,.col-sm-auto,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-md,.col-md-auto,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg,.col-lg-auto,.col-xl-1,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-1{margin-left:8.3333333333%}.offset-2{margin-left:16.6666666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.3333333333%}.offset-5{margin-left:41.6666666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.3333333333%}.offset-8{margin-left:66.6666666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.3333333333%}.offset-11{margin-left:91.6666666667%}@media (min-width: 576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-sm-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-sm-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-sm-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-sm-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-sm-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-sm-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-sm-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-sm-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-sm-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-sm-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-sm-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-sm-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-sm-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-sm-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-sm-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-sm-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-sm-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-sm-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-sm-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-sm-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-sm-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-sm-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.3333333333%}.offset-sm-2{margin-left:16.6666666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.3333333333%}.offset-sm-5{margin-left:41.6666666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.3333333333%}.offset-sm-8{margin-left:66.6666666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.3333333333%}.offset-sm-11{margin-left:91.6666666667%}}@media (min-width: 768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-md-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-md-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-md-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-md-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-md-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-md-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-md-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-md-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-md-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-md-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-md-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-md-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-md-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-md-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-md-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-md-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-md-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-md-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-md-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-md-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-md-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-md-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.3333333333%}.offset-md-2{margin-left:16.6666666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.3333333333%}.offset-md-5{margin-left:41.6666666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.3333333333%}.offset-md-8{margin-left:66.6666666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.3333333333%}.offset-md-11{margin-left:91.6666666667%}}@media (min-width: 992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-lg-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-lg-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-lg-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-lg-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-lg-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-lg-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-lg-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-lg-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-lg-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-lg-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-lg-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-lg-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-lg-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-lg-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-lg-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-lg-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-lg-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-lg-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-lg-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-lg-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-lg-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-lg-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.3333333333%}.offset-lg-2{margin-left:16.6666666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.3333333333%}.offset-lg-5{margin-left:41.6666666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.3333333333%}.offset-lg-8{margin-left:66.6666666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.3333333333%}.offset-lg-11{margin-left:91.6666666667%}}@media (min-width: 1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-webkit-box-flex:0;-ms-flex:0 0 8.3333333333%;flex:0 0 8.3333333333%;max-width:8.3333333333%}.col-xl-2{-webkit-box-flex:0;-ms-flex:0 0 16.6666666667%;flex:0 0 16.6666666667%;max-width:16.6666666667%}.col-xl-3{-webkit-box-flex:0;-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-webkit-box-flex:0;-ms-flex:0 0 33.3333333333%;flex:0 0 33.3333333333%;max-width:33.3333333333%}.col-xl-5{-webkit-box-flex:0;-ms-flex:0 0 41.6666666667%;flex:0 0 41.6666666667%;max-width:41.6666666667%}.col-xl-6{-webkit-box-flex:0;-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-webkit-box-flex:0;-ms-flex:0 0 58.3333333333%;flex:0 0 58.3333333333%;max-width:58.3333333333%}.col-xl-8{-webkit-box-flex:0;-ms-flex:0 0 66.6666666667%;flex:0 0 66.6666666667%;max-width:66.6666666667%}.col-xl-9{-webkit-box-flex:0;-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-webkit-box-flex:0;-ms-flex:0 0 83.3333333333%;flex:0 0 83.3333333333%;max-width:83.3333333333%}.col-xl-11{-webkit-box-flex:0;-ms-flex:0 0 91.6666666667%;flex:0 0 91.6666666667%;max-width:91.6666666667%}.col-xl-12{-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.order-xl-last{-webkit-box-ordinal-group:14;-ms-flex-order:13;order:13}.order-xl-0{-webkit-box-ordinal-group:1;-ms-flex-order:0;order:0}.order-xl-1{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.order-xl-2{-webkit-box-ordinal-group:3;-ms-flex-order:2;order:2}.order-xl-3{-webkit-box-ordinal-group:4;-ms-flex-order:3;order:3}.order-xl-4{-webkit-box-ordinal-group:5;-ms-flex-order:4;order:4}.order-xl-5{-webkit-box-ordinal-group:6;-ms-flex-order:5;order:5}.order-xl-6{-webkit-box-ordinal-group:7;-ms-flex-order:6;order:6}.order-xl-7{-webkit-box-ordinal-group:8;-ms-flex-order:7;order:7}.order-xl-8{-webkit-box-ordinal-group:9;-ms-flex-order:8;order:8}.order-xl-9{-webkit-box-ordinal-group:10;-ms-flex-order:9;order:9}.order-xl-10{-webkit-box-ordinal-group:11;-ms-flex-order:10;order:10}.order-xl-11{-webkit-box-ordinal-group:12;-ms-flex-order:11;order:11}.order-xl-12{-webkit-box-ordinal-group:13;-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.3333333333%}.offset-xl-2{margin-left:16.6666666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.3333333333%}.offset-xl-5{margin-left:41.6666666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.3333333333%}.offset-xl-8{margin-left:66.6666666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.3333333333%}.offset-xl-11{margin-left:91.6666666667%}}.d-none{display:none !important}.d-inline{display:inline !important}.d-inline-block{display:inline-block !important}.d-block{display:block !important}.d-table{display:table !important}.d-table-row{display:table-row !important}.d-table-cell{display:table-cell !important}.d-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}@media (min-width: 576px){.d-sm-none{display:none !important}.d-sm-inline{display:inline !important}.d-sm-inline-block{display:inline-block !important}.d-sm-block{display:block !important}.d-sm-table{display:table !important}.d-sm-table-row{display:table-row !important}.d-sm-table-cell{display:table-cell !important}.d-sm-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-sm-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 768px){.d-md-none{display:none !important}.d-md-inline{display:inline !important}.d-md-inline-block{display:inline-block !important}.d-md-block{display:block !important}.d-md-table{display:table !important}.d-md-table-row{display:table-row !important}.d-md-table-cell{display:table-cell !important}.d-md-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-md-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 992px){.d-lg-none{display:none !important}.d-lg-inline{display:inline !important}.d-lg-inline-block{display:inline-block !important}.d-lg-block{display:block !important}.d-lg-table{display:table !important}.d-lg-table-row{display:table-row !important}.d-lg-table-cell{display:table-cell !important}.d-lg-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-lg-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media (min-width: 1200px){.d-xl-none{display:none !important}.d-xl-inline{display:inline !important}.d-xl-inline-block{display:inline-block !important}.d-xl-block{display:block !important}.d-xl-table{display:table !important}.d-xl-table-row{display:table-row !important}.d-xl-table-cell{display:table-cell !important}.d-xl-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-xl-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}@media print{.d-print-none{display:none !important}.d-print-inline{display:inline !important}.d-print-inline-block{display:inline-block !important}.d-print-block{display:block !important}.d-print-table{display:table !important}.d-print-table-row{display:table-row !important}.d-print-table-cell{display:table-cell !important}.d-print-flex{display:-webkit-box !important;display:-ms-flexbox !important;display:flex !important}.d-print-inline-flex{display:-webkit-inline-box !important;display:-ms-inline-flexbox !important;display:inline-flex !important}}.flex-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}@media (min-width: 576px){.flex-sm-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-sm-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-sm-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-sm-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-sm-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-sm-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-sm-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-sm-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-sm-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-sm-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-sm-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-sm-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-sm-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-sm-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-sm-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-sm-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-sm-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-sm-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-sm-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-sm-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-sm-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-sm-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-sm-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-sm-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-sm-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-sm-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-sm-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-sm-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-sm-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-sm-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-sm-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-sm-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-sm-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 768px){.flex-md-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-md-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-md-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-md-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-md-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-md-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-md-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-md-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-md-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-md-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-md-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-md-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-md-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-md-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-md-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-md-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-md-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-md-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-md-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-md-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-md-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-md-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-md-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-md-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-md-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-md-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-md-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-md-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-md-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-md-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-md-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-md-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-md-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 992px){.flex-lg-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-lg-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-lg-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-lg-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-lg-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-lg-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-lg-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-lg-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-lg-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-lg-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-lg-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-lg-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-lg-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-lg-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-lg-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-lg-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-lg-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-lg-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-lg-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-lg-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-lg-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-lg-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-lg-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-lg-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-lg-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-lg-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-lg-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-lg-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-lg-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-lg-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-lg-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-lg-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-lg-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}@media (min-width: 1200px){.flex-xl-row{-webkit-box-orient:horizontal !important;-webkit-box-direction:normal !important;-ms-flex-direction:row !important;flex-direction:row !important}.flex-xl-column{-webkit-box-orient:vertical !important;-webkit-box-direction:normal !important;-ms-flex-direction:column !important;flex-direction:column !important}.flex-xl-row-reverse{-webkit-box-orient:horizontal !important;-webkit-box-direction:reverse !important;-ms-flex-direction:row-reverse !important;flex-direction:row-reverse !important}.flex-xl-column-reverse{-webkit-box-orient:vertical !important;-webkit-box-direction:reverse !important;-ms-flex-direction:column-reverse !important;flex-direction:column-reverse !important}.flex-xl-wrap{-ms-flex-wrap:wrap !important;flex-wrap:wrap !important}.flex-xl-nowrap{-ms-flex-wrap:nowrap !important;flex-wrap:nowrap !important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse !important;flex-wrap:wrap-reverse !important}.flex-xl-fill{-webkit-box-flex:1 !important;-ms-flex:1 1 auto !important;flex:1 1 auto !important}.flex-xl-grow-0{-webkit-box-flex:0 !important;-ms-flex-positive:0 !important;flex-grow:0 !important}.flex-xl-grow-1{-webkit-box-flex:1 !important;-ms-flex-positive:1 !important;flex-grow:1 !important}.flex-xl-shrink-0{-ms-flex-negative:0 !important;flex-shrink:0 !important}.flex-xl-shrink-1{-ms-flex-negative:1 !important;flex-shrink:1 !important}.justify-content-xl-start{-webkit-box-pack:start !important;-ms-flex-pack:start !important;justify-content:flex-start !important}.justify-content-xl-end{-webkit-box-pack:end !important;-ms-flex-pack:end !important;justify-content:flex-end !important}.justify-content-xl-center{-webkit-box-pack:center !important;-ms-flex-pack:center !important;justify-content:center !important}.justify-content-xl-between{-webkit-box-pack:justify !important;-ms-flex-pack:justify !important;justify-content:space-between !important}.justify-content-xl-around{-ms-flex-pack:distribute !important;justify-content:space-around !important}.align-items-xl-start{-webkit-box-align:start !important;-ms-flex-align:start !important;align-items:flex-start !important}.align-items-xl-end{-webkit-box-align:end !important;-ms-flex-align:end !important;align-items:flex-end !important}.align-items-xl-center{-webkit-box-align:center !important;-ms-flex-align:center !important;align-items:center !important}.align-items-xl-baseline{-webkit-box-align:baseline !important;-ms-flex-align:baseline !important;align-items:baseline !important}.align-items-xl-stretch{-webkit-box-align:stretch !important;-ms-flex-align:stretch !important;align-items:stretch !important}.align-content-xl-start{-ms-flex-line-pack:start !important;align-content:flex-start !important}.align-content-xl-end{-ms-flex-line-pack:end !important;align-content:flex-end !important}.align-content-xl-center{-ms-flex-line-pack:center !important;align-content:center !important}.align-content-xl-between{-ms-flex-line-pack:justify !important;align-content:space-between !important}.align-content-xl-around{-ms-flex-line-pack:distribute !important;align-content:space-around !important}.align-content-xl-stretch{-ms-flex-line-pack:stretch !important;align-content:stretch !important}.align-self-xl-auto{-ms-flex-item-align:auto !important;align-self:auto !important}.align-self-xl-start{-ms-flex-item-align:start !important;align-self:flex-start !important}.align-self-xl-end{-ms-flex-item-align:end !important;align-self:flex-end !important}.align-self-xl-center{-ms-flex-item-align:center !important;align-self:center !important}.align-self-xl-baseline{-ms-flex-item-align:baseline !important;align-self:baseline !important}.align-self-xl-stretch{-ms-flex-item-align:stretch !important;align-self:stretch !important}}.w-25{width:25% !important}.w-50{width:50% !important}.w-75{width:75% !important}.w-100{width:100% !important}.w-auto{width:auto !important}.h-25{height:25% !important}.h-50{height:50% !important}.h-75{height:75% !important}.h-100{height:100% !important}.h-auto{height:auto !important}.mw-100{max-width:100% !important}.mh-100{max-height:100% !important}.m-0{margin:0 !important}.mt-0,.my-0{margin-top:0 !important}.mr-0,.mx-0{margin-right:0 !important}.mb-0,.my-0{margin-bottom:0 !important}.ml-0,.mx-0{margin-left:0 !important}.m-1{margin:0.25rem !important}.mt-1,.my-1{margin-top:0.25rem !important}.mr-1,.mx-1{margin-right:0.25rem !important}.mb-1,.my-1{margin-bottom:0.25rem !important}.ml-1,.mx-1{margin-left:0.25rem !important}.m-2{margin:0.5rem !important}.mt-2,.my-2{margin-top:0.5rem !important}.mr-2,.mx-2{margin-right:0.5rem !important}.mb-2,.my-2{margin-bottom:0.5rem !important}.ml-2,.mx-2{margin-left:0.5rem !important}.m-3{margin:1rem !important}.mt-3,.my-3{margin-top:1rem !important}.mr-3,.mx-3{margin-right:1rem !important}.mb-3,.my-3{margin-bottom:1rem !important}.ml-3,.mx-3{margin-left:1rem !important}.m-4{margin:1.5rem !important}.mt-4,.my-4{margin-top:1.5rem !important}.mr-4,.mx-4{margin-right:1.5rem !important}.mb-4,.my-4{margin-bottom:1.5rem !important}.ml-4,.mx-4{margin-left:1.5rem !important}.m-5{margin:3rem !important}.mt-5,.my-5{margin-top:3rem !important}.mr-5,.mx-5{margin-right:3rem !important}.mb-5,.my-5{margin-bottom:3rem !important}.ml-5,.mx-5{margin-left:3rem !important}.p-0{padding:0 !important}.pt-0,.py-0{padding-top:0 !important}.pr-0,.px-0{padding-right:0 !important}.pb-0,.py-0{padding-bottom:0 !important}.pl-0,.px-0{padding-left:0 !important}.p-1{padding:0.25rem !important}.pt-1,.py-1{padding-top:0.25rem !important}.pr-1,.px-1{padding-right:0.25rem !important}.pb-1,.py-1{padding-bottom:0.25rem !important}.pl-1,.px-1{padding-left:0.25rem !important}.p-2{padding:0.5rem !important}.pt-2,.py-2{padding-top:0.5rem !important}.pr-2,.px-2{padding-right:0.5rem !important}.pb-2,.py-2{padding-bottom:0.5rem !important}.pl-2,.px-2{padding-left:0.5rem !important}.p-3{padding:1rem !important}.pt-3,.py-3{padding-top:1rem !important}.pr-3,.px-3{padding-right:1rem !important}.pb-3,.py-3{padding-bottom:1rem !important}.pl-3,.px-3{padding-left:1rem !important}.p-4{padding:1.5rem !important}.pt-4,.py-4{padding-top:1.5rem !important}.pr-4,.px-4{padding-right:1.5rem !important}.pb-4,.py-4{padding-bottom:1.5rem !important}.pl-4,.px-4{padding-left:1.5rem !important}.p-5{padding:3rem !important}.pt-5,.py-5{padding-top:3rem !important}.pr-5,.px-5{padding-right:3rem !important}.pb-5,.py-5{padding-bottom:3rem !important}.pl-5,.px-5{padding-left:3rem !important}.m-auto{margin:auto !important}.mt-auto,.my-auto{margin-top:auto !important}.mr-auto,.mx-auto{margin-right:auto !important}.mb-auto,.my-auto{margin-bottom:auto !important}.ml-auto,.mx-auto{margin-left:auto !important}@media (min-width: 576px){.m-sm-0{margin:0 !important}.mt-sm-0,.my-sm-0{margin-top:0 !important}.mr-sm-0,.mx-sm-0{margin-right:0 !important}.mb-sm-0,.my-sm-0{margin-bottom:0 !important}.ml-sm-0,.mx-sm-0{margin-left:0 !important}.m-sm-1{margin:0.25rem !important}.mt-sm-1,.my-sm-1{margin-top:0.25rem !important}.mr-sm-1,.mx-sm-1{margin-right:0.25rem !important}.mb-sm-1,.my-sm-1{margin-bottom:0.25rem !important}.ml-sm-1,.mx-sm-1{margin-left:0.25rem !important}.m-sm-2{margin:0.5rem !important}.mt-sm-2,.my-sm-2{margin-top:0.5rem !important}.mr-sm-2,.mx-sm-2{margin-right:0.5rem !important}.mb-sm-2,.my-sm-2{margin-bottom:0.5rem !important}.ml-sm-2,.mx-sm-2{margin-left:0.5rem !important}.m-sm-3{margin:1rem !important}.mt-sm-3,.my-sm-3{margin-top:1rem !important}.mr-sm-3,.mx-sm-3{margin-right:1rem !important}.mb-sm-3,.my-sm-3{margin-bottom:1rem !important}.ml-sm-3,.mx-sm-3{margin-left:1rem !important}.m-sm-4{margin:1.5rem !important}.mt-sm-4,.my-sm-4{margin-top:1.5rem !important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem !important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem !important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem !important}.m-sm-5{margin:3rem !important}.mt-sm-5,.my-sm-5{margin-top:3rem !important}.mr-sm-5,.mx-sm-5{margin-right:3rem !important}.mb-sm-5,.my-sm-5{margin-bottom:3rem !important}.ml-sm-5,.mx-sm-5{margin-left:3rem !important}.p-sm-0{padding:0 !important}.pt-sm-0,.py-sm-0{padding-top:0 !important}.pr-sm-0,.px-sm-0{padding-right:0 !important}.pb-sm-0,.py-sm-0{padding-bottom:0 !important}.pl-sm-0,.px-sm-0{padding-left:0 !important}.p-sm-1{padding:0.25rem !important}.pt-sm-1,.py-sm-1{padding-top:0.25rem !important}.pr-sm-1,.px-sm-1{padding-right:0.25rem !important}.pb-sm-1,.py-sm-1{padding-bottom:0.25rem !important}.pl-sm-1,.px-sm-1{padding-left:0.25rem !important}.p-sm-2{padding:0.5rem !important}.pt-sm-2,.py-sm-2{padding-top:0.5rem !important}.pr-sm-2,.px-sm-2{padding-right:0.5rem !important}.pb-sm-2,.py-sm-2{padding-bottom:0.5rem !important}.pl-sm-2,.px-sm-2{padding-left:0.5rem !important}.p-sm-3{padding:1rem !important}.pt-sm-3,.py-sm-3{padding-top:1rem !important}.pr-sm-3,.px-sm-3{padding-right:1rem !important}.pb-sm-3,.py-sm-3{padding-bottom:1rem !important}.pl-sm-3,.px-sm-3{padding-left:1rem !important}.p-sm-4{padding:1.5rem !important}.pt-sm-4,.py-sm-4{padding-top:1.5rem !important}.pr-sm-4,.px-sm-4{padding-right:1.5rem !important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem !important}.pl-sm-4,.px-sm-4{padding-left:1.5rem !important}.p-sm-5{padding:3rem !important}.pt-sm-5,.py-sm-5{padding-top:3rem !important}.pr-sm-5,.px-sm-5{padding-right:3rem !important}.pb-sm-5,.py-sm-5{padding-bottom:3rem !important}.pl-sm-5,.px-sm-5{padding-left:3rem !important}.m-sm-auto{margin:auto !important}.mt-sm-auto,.my-sm-auto{margin-top:auto !important}.mr-sm-auto,.mx-sm-auto{margin-right:auto !important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto !important}.ml-sm-auto,.mx-sm-auto{margin-left:auto !important}}@media (min-width: 768px){.m-md-0{margin:0 !important}.mt-md-0,.my-md-0{margin-top:0 !important}.mr-md-0,.mx-md-0{margin-right:0 !important}.mb-md-0,.my-md-0{margin-bottom:0 !important}.ml-md-0,.mx-md-0{margin-left:0 !important}.m-md-1{margin:0.25rem !important}.mt-md-1,.my-md-1{margin-top:0.25rem !important}.mr-md-1,.mx-md-1{margin-right:0.25rem !important}.mb-md-1,.my-md-1{margin-bottom:0.25rem !important}.ml-md-1,.mx-md-1{margin-left:0.25rem !important}.m-md-2{margin:0.5rem !important}.mt-md-2,.my-md-2{margin-top:0.5rem !important}.mr-md-2,.mx-md-2{margin-right:0.5rem !important}.mb-md-2,.my-md-2{margin-bottom:0.5rem !important}.ml-md-2,.mx-md-2{margin-left:0.5rem !important}.m-md-3{margin:1rem !important}.mt-md-3,.my-md-3{margin-top:1rem !important}.mr-md-3,.mx-md-3{margin-right:1rem !important}.mb-md-3,.my-md-3{margin-bottom:1rem !important}.ml-md-3,.mx-md-3{margin-left:1rem !important}.m-md-4{margin:1.5rem !important}.mt-md-4,.my-md-4{margin-top:1.5rem !important}.mr-md-4,.mx-md-4{margin-right:1.5rem !important}.mb-md-4,.my-md-4{margin-bottom:1.5rem !important}.ml-md-4,.mx-md-4{margin-left:1.5rem !important}.m-md-5{margin:3rem !important}.mt-md-5,.my-md-5{margin-top:3rem !important}.mr-md-5,.mx-md-5{margin-right:3rem !important}.mb-md-5,.my-md-5{margin-bottom:3rem !important}.ml-md-5,.mx-md-5{margin-left:3rem !important}.p-md-0{padding:0 !important}.pt-md-0,.py-md-0{padding-top:0 !important}.pr-md-0,.px-md-0{padding-right:0 !important}.pb-md-0,.py-md-0{padding-bottom:0 !important}.pl-md-0,.px-md-0{padding-left:0 !important}.p-md-1{padding:0.25rem !important}.pt-md-1,.py-md-1{padding-top:0.25rem !important}.pr-md-1,.px-md-1{padding-right:0.25rem !important}.pb-md-1,.py-md-1{padding-bottom:0.25rem !important}.pl-md-1,.px-md-1{padding-left:0.25rem !important}.p-md-2{padding:0.5rem !important}.pt-md-2,.py-md-2{padding-top:0.5rem !important}.pr-md-2,.px-md-2{padding-right:0.5rem !important}.pb-md-2,.py-md-2{padding-bottom:0.5rem !important}.pl-md-2,.px-md-2{padding-left:0.5rem !important}.p-md-3{padding:1rem !important}.pt-md-3,.py-md-3{padding-top:1rem !important}.pr-md-3,.px-md-3{padding-right:1rem !important}.pb-md-3,.py-md-3{padding-bottom:1rem !important}.pl-md-3,.px-md-3{padding-left:1rem !important}.p-md-4{padding:1.5rem !important}.pt-md-4,.py-md-4{padding-top:1.5rem !important}.pr-md-4,.px-md-4{padding-right:1.5rem !important}.pb-md-4,.py-md-4{padding-bottom:1.5rem !important}.pl-md-4,.px-md-4{padding-left:1.5rem !important}.p-md-5{padding:3rem !important}.pt-md-5,.py-md-5{padding-top:3rem !important}.pr-md-5,.px-md-5{padding-right:3rem !important}.pb-md-5,.py-md-5{padding-bottom:3rem !important}.pl-md-5,.px-md-5{padding-left:3rem !important}.m-md-auto{margin:auto !important}.mt-md-auto,.my-md-auto{margin-top:auto !important}.mr-md-auto,.mx-md-auto{margin-right:auto !important}.mb-md-auto,.my-md-auto{margin-bottom:auto !important}.ml-md-auto,.mx-md-auto{margin-left:auto !important}}@media (min-width: 992px){.m-lg-0{margin:0 !important}.mt-lg-0,.my-lg-0{margin-top:0 !important}.mr-lg-0,.mx-lg-0{margin-right:0 !important}.mb-lg-0,.my-lg-0{margin-bottom:0 !important}.ml-lg-0,.mx-lg-0{margin-left:0 !important}.m-lg-1{margin:0.25rem !important}.mt-lg-1,.my-lg-1{margin-top:0.25rem !important}.mr-lg-1,.mx-lg-1{margin-right:0.25rem !important}.mb-lg-1,.my-lg-1{margin-bottom:0.25rem !important}.ml-lg-1,.mx-lg-1{margin-left:0.25rem !important}.m-lg-2{margin:0.5rem !important}.mt-lg-2,.my-lg-2{margin-top:0.5rem !important}.mr-lg-2,.mx-lg-2{margin-right:0.5rem !important}.mb-lg-2,.my-lg-2{margin-bottom:0.5rem !important}.ml-lg-2,.mx-lg-2{margin-left:0.5rem !important}.m-lg-3{margin:1rem !important}.mt-lg-3,.my-lg-3{margin-top:1rem !important}.mr-lg-3,.mx-lg-3{margin-right:1rem !important}.mb-lg-3,.my-lg-3{margin-bottom:1rem !important}.ml-lg-3,.mx-lg-3{margin-left:1rem !important}.m-lg-4{margin:1.5rem !important}.mt-lg-4,.my-lg-4{margin-top:1.5rem !important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem !important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem !important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem !important}.m-lg-5{margin:3rem !important}.mt-lg-5,.my-lg-5{margin-top:3rem !important}.mr-lg-5,.mx-lg-5{margin-right:3rem !important}.mb-lg-5,.my-lg-5{margin-bottom:3rem !important}.ml-lg-5,.mx-lg-5{margin-left:3rem !important}.p-lg-0{padding:0 !important}.pt-lg-0,.py-lg-0{padding-top:0 !important}.pr-lg-0,.px-lg-0{padding-right:0 !important}.pb-lg-0,.py-lg-0{padding-bottom:0 !important}.pl-lg-0,.px-lg-0{padding-left:0 !important}.p-lg-1{padding:0.25rem !important}.pt-lg-1,.py-lg-1{padding-top:0.25rem !important}.pr-lg-1,.px-lg-1{padding-right:0.25rem !important}.pb-lg-1,.py-lg-1{padding-bottom:0.25rem !important}.pl-lg-1,.px-lg-1{padding-left:0.25rem !important}.p-lg-2{padding:0.5rem !important}.pt-lg-2,.py-lg-2{padding-top:0.5rem !important}.pr-lg-2,.px-lg-2{padding-right:0.5rem !important}.pb-lg-2,.py-lg-2{padding-bottom:0.5rem !important}.pl-lg-2,.px-lg-2{padding-left:0.5rem !important}.p-lg-3{padding:1rem !important}.pt-lg-3,.py-lg-3{padding-top:1rem !important}.pr-lg-3,.px-lg-3{padding-right:1rem !important}.pb-lg-3,.py-lg-3{padding-bottom:1rem !important}.pl-lg-3,.px-lg-3{padding-left:1rem !important}.p-lg-4{padding:1.5rem !important}.pt-lg-4,.py-lg-4{padding-top:1.5rem !important}.pr-lg-4,.px-lg-4{padding-right:1.5rem !important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem !important}.pl-lg-4,.px-lg-4{padding-left:1.5rem !important}.p-lg-5{padding:3rem !important}.pt-lg-5,.py-lg-5{padding-top:3rem !important}.pr-lg-5,.px-lg-5{padding-right:3rem !important}.pb-lg-5,.py-lg-5{padding-bottom:3rem !important}.pl-lg-5,.px-lg-5{padding-left:3rem !important}.m-lg-auto{margin:auto !important}.mt-lg-auto,.my-lg-auto{margin-top:auto !important}.mr-lg-auto,.mx-lg-auto{margin-right:auto !important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto !important}.ml-lg-auto,.mx-lg-auto{margin-left:auto !important}}@media (min-width: 1200px){.m-xl-0{margin:0 !important}.mt-xl-0,.my-xl-0{margin-top:0 !important}.mr-xl-0,.mx-xl-0{margin-right:0 !important}.mb-xl-0,.my-xl-0{margin-bottom:0 !important}.ml-xl-0,.mx-xl-0{margin-left:0 !important}.m-xl-1{margin:0.25rem !important}.mt-xl-1,.my-xl-1{margin-top:0.25rem !important}.mr-xl-1,.mx-xl-1{margin-right:0.25rem !important}.mb-xl-1,.my-xl-1{margin-bottom:0.25rem !important}.ml-xl-1,.mx-xl-1{margin-left:0.25rem !important}.m-xl-2{margin:0.5rem !important}.mt-xl-2,.my-xl-2{margin-top:0.5rem !important}.mr-xl-2,.mx-xl-2{margin-right:0.5rem !important}.mb-xl-2,.my-xl-2{margin-bottom:0.5rem !important}.ml-xl-2,.mx-xl-2{margin-left:0.5rem !important}.m-xl-3{margin:1rem !important}.mt-xl-3,.my-xl-3{margin-top:1rem !important}.mr-xl-3,.mx-xl-3{margin-right:1rem !important}.mb-xl-3,.my-xl-3{margin-bottom:1rem !important}.ml-xl-3,.mx-xl-3{margin-left:1rem !important}.m-xl-4{margin:1.5rem !important}.mt-xl-4,.my-xl-4{margin-top:1.5rem !important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem !important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem !important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem !important}.m-xl-5{margin:3rem !important}.mt-xl-5,.my-xl-5{margin-top:3rem !important}.mr-xl-5,.mx-xl-5{margin-right:3rem !important}.mb-xl-5,.my-xl-5{margin-bottom:3rem !important}.ml-xl-5,.mx-xl-5{margin-left:3rem !important}.p-xl-0{padding:0 !important}.pt-xl-0,.py-xl-0{padding-top:0 !important}.pr-xl-0,.px-xl-0{padding-right:0 !important}.pb-xl-0,.py-xl-0{padding-bottom:0 !important}.pl-xl-0,.px-xl-0{padding-left:0 !important}.p-xl-1{padding:0.25rem !important}.pt-xl-1,.py-xl-1{padding-top:0.25rem !important}.pr-xl-1,.px-xl-1{padding-right:0.25rem !important}.pb-xl-1,.py-xl-1{padding-bottom:0.25rem !important}.pl-xl-1,.px-xl-1{padding-left:0.25rem !important}.p-xl-2{padding:0.5rem !important}.pt-xl-2,.py-xl-2{padding-top:0.5rem !important}.pr-xl-2,.px-xl-2{padding-right:0.5rem !important}.pb-xl-2,.py-xl-2{padding-bottom:0.5rem !important}.pl-xl-2,.px-xl-2{padding-left:0.5rem !important}.p-xl-3{padding:1rem !important}.pt-xl-3,.py-xl-3{padding-top:1rem !important}.pr-xl-3,.px-xl-3{padding-right:1rem !important}.pb-xl-3,.py-xl-3{padding-bottom:1rem !important}.pl-xl-3,.px-xl-3{padding-left:1rem !important}.p-xl-4{padding:1.5rem !important}.pt-xl-4,.py-xl-4{padding-top:1.5rem !important}.pr-xl-4,.px-xl-4{padding-right:1.5rem !important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem !important}.pl-xl-4,.px-xl-4{padding-left:1.5rem !important}.p-xl-5{padding:3rem !important}.pt-xl-5,.py-xl-5{padding-top:3rem !important}.pr-xl-5,.px-xl-5{padding-right:3rem !important}.pb-xl-5,.py-xl-5{padding-bottom:3rem !important}.pl-xl-5,.px-xl-5{padding-left:3rem !important}.m-xl-auto{margin:auto !important}.mt-xl-auto,.my-xl-auto{margin-top:auto !important}.mr-xl-auto,.mx-xl-auto{margin-right:auto !important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto !important}.ml-xl-auto,.mx-xl-auto{margin-left:auto !important}}.visible{visibility:visible !important}.invisible{visibility:hidden !important} diff --git a/css/milestones.scss b/css/milestones.scss index d76c6557b..74c8c11e3 100644 --- a/css/milestones.scss +++ b/css/milestones.scss @@ -2,4 +2,4 @@ position: fixed; padding: 6px; width: 60%; -} \ No newline at end of file +} diff --git a/css/redpill.scss b/css/redpill.scss index 1811b8b91..7bcedc6a6 100644 --- a/css/redpill.scss +++ b/css/redpill.scss @@ -17,7 +17,7 @@ } &.level-2 { - color: #48D1CC; + color: #48d1cc; } &.level-3 { diff --git a/css/resleeving.scss b/css/resleeving.scss index d728013cf..37873377a 100644 --- a/css/resleeving.scss +++ b/css/resleeving.scss @@ -1,4 +1,4 @@ - /** +/** * Styling for the Re-Sleeving Page */ @import "theme"; @@ -15,7 +15,7 @@ .resleeve-panel { display: inline-block; - margin: 0px; + margin: 0; padding: 2px; } diff --git a/css/sleeves.scss b/css/sleeves.scss index 9ef3d601c..ffea27ba9 100644 --- a/css/sleeves.scss +++ b/css/sleeves.scss @@ -20,7 +20,7 @@ .sleeve-panel { display: inline-block; - margin: 0px; + margin: 0; padding: 2px; select { diff --git a/css/styles.scss b/css/styles.scss index c093908f5..a6c98b897 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -375,7 +375,7 @@ a:visited { } .noscrollbar::-webkit-scrollbar { - display: none; + display: none; } input[type=checkbox] { @@ -383,42 +383,42 @@ input[type=checkbox] { } .optionCheckbox { - margin: 5px; - float: right; + margin: 5px; + float: right; } .optionRange { - -webkit-appearance: none; - background: #777; - outline: none; - opacity: 0.7; - height: 10px; - -webkit-transition: .2s; - transition: opacity .2s; - margin: 3px; + -webkit-appearance: none; + background: #777; + outline: none; + opacity: 0.7; + height: 10px; + -webkit-transition: 0.2s; + transition: opacity 0.2s; + margin: 3px; } .optionRange::-webkit-slider-thumb { - -webkit-appearance: none; - appearance: none; - width: 10px; - height: 10px; - background: var(--my-font-color); - cursor: pointer; + -webkit-appearance: none; + appearance: none; + width: 10px; + height: 10px; + background: var(--my-font-color); + cursor: pointer; } .optionRange::-moz-range-thumb { - width: 10px; - height: 10px; - background: var(--my-font-color); - cursor: pointer; + width: 10px; + height: 10px; + background: var(--my-font-color); + cursor: pointer; } .noselect { - -moz-user-select: -moz-none; - -khtml-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; -} \ No newline at end of file + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; +} diff --git a/css/tooltips.scss b/css/tooltips.scss index 4f58842d5..8a5971918 100644 --- a/css/tooltips.scss +++ b/css/tooltips.scss @@ -35,7 +35,7 @@ left: 50%; transform: translate(-100%, -100%); - /* Backwards compatibility */ + /* Backwards compatibility */ -webkit-transform: translate(-100%, -100%); -moz-transform: translate(-100%, -100%); -o-transform: translate(-100%, -100%); @@ -126,4 +126,4 @@ visibility: visible; opacity: 1; transition: opacity 0.3s; -} \ No newline at end of file +} diff --git a/css/treant.css b/css/treant.css index d4e6c73dc..38917ce34 100644 --- a/css/treant.css +++ b/css/treant.css @@ -7,16 +7,16 @@ .Treant.Treant-loaded .pseudo { visibility: visible; } .Treant > .pseudo { width: 0; height: 0; border: none; padding: 0; } .Treant .collapse-switch { width: 3px; height: 3px; display: block; border: 1px solid black; position: absolute; top: 1px; right: 1px; cursor: pointer; } -.Treant .collapsed .collapse-switch { background-color: #868DEE; } +.Treant .collapsed .collapse-switch { background-color: #868dee; } .Treant > .node img { border: none; float: left; } .Treant > .node { cursor: pointer; - padding: 4px; - min-width: 60px; - text-align: center; - border: 2px solid #E8E8E3; - border-radius: 2px; - box-shadow: 1px 1px 1px rgba(0,0,0,.5); + padding: 4px; + min-width: 60px; + text-align: center; + border: 2px solid #e8e8e3; + border-radius: 2px; + box-shadow: 1px 1px 1px rgba(0,0,0,0.5); font-size: 12px; } diff --git a/doc/source/basicgameplay/augmentations.rst b/doc/source/basicgameplay/augmentations.rst index a79dce68f..1a19883d2 100644 --- a/doc/source/basicgameplay/augmentations.rst +++ b/doc/source/basicgameplay/augmentations.rst @@ -11,7 +11,7 @@ user's physical and mental faculties. Augmentations provide persistent upgrades in the form of multipliers. These multipliers apply to a wide variety of things such as stats, experience gain, and hacking, just to name a few. Your multipliers -can be viewed in the 'Character' page (:ref:`keyboard shortcut ` Alt + c) +can be viewed in the 'Character' page (:ref:`keyboard shortcut ` Alt + c). How to acquire Augmentations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/source/netscript/basicfunctions/getServerMaxRam.rst b/doc/source/netscript/basicfunctions/getServerMaxRam.rst new file mode 100644 index 000000000..d895c494e --- /dev/null +++ b/doc/source/netscript/basicfunctions/getServerMaxRam.rst @@ -0,0 +1,15 @@ +getServerMaxRam() Netscript Function +==================================== + +.. js:function:: getServerMaxRam(hostname) + + :RAM cost: 0.05 GB + :param string hostname: Hostname of target server. + :returns: Total ram available on that server. In GB. + + Example: + + .. code-block:: javascript + + maxRam = getServerMaxRam("helios"); // returns: 16 + print("helios has "+maxRam + "GB"); diff --git a/doc/source/netscript/basicfunctions/getServerRam.rst b/doc/source/netscript/basicfunctions/getServerRam.rst index 40e46df42..70d3ce032 100644 --- a/doc/source/netscript/basicfunctions/getServerRam.rst +++ b/doc/source/netscript/basicfunctions/getServerRam.rst @@ -3,6 +3,8 @@ getServerRam() Netscript Function .. js:function:: getServerRam(hostname) + .. warning:: This function is deprecated. + :RAM cost: 0.1 GB :param string hostname: Hostname of target server. :returns: An array of 2 number, first number is the total RAM, second the diff --git a/doc/source/netscript/basicfunctions/getServerUsedRam.rst b/doc/source/netscript/basicfunctions/getServerUsedRam.rst new file mode 100644 index 000000000..878389cb0 --- /dev/null +++ b/doc/source/netscript/basicfunctions/getServerUsedRam.rst @@ -0,0 +1,15 @@ +getServerUsedRam() Netscript Function +===================================== + +.. js:function:: getServerUsedRam(hostname) + + :RAM cost: 0.05 GB + :param string hostname: Hostname of target server. + :returns: Used ram on that server. In GB. + + Example: + + .. code-block:: javascript + + usedRam = getServerUsedRam("harakiri-sushi"); // returns: 5.6 + print("harakiri-sushi uses "+usedRam + "GB"); diff --git a/doc/source/netscript/netscriptbladeburnerapi.rst b/doc/source/netscript/netscriptbladeburnerapi.rst index dbd487b73..6f5638c0a 100644 --- a/doc/source/netscript/netscriptbladeburnerapi.rst +++ b/doc/source/netscript/netscriptbladeburnerapi.rst @@ -5,13 +5,13 @@ Netscript Bladeburner API Netscript provides the following API for interacting with the game's Bladeburner mechanic. The Bladeburner API is **not** immediately available to the player and must be unlocked -later in the game +later in the game. .. warning:: This page contains spoilers for the game The Bladeburner API is unlocked in BitNode-7. If you are in BitNode-7, you will automatically gain access to this API. Otherwise, you must have Source-File 7 in -order to use this API in other BitNodes +order to use this API in other BitNodes. **Bladeburner API functions must be accessed through the 'bladeburner' namespace** @@ -157,7 +157,7 @@ identifier by attaching the Bladeburner API functions to an object:: } BladeburnerHandler.prototype.handle = function() { - //If we're doing something else manually (without Simlacrum), + //If we're doing something else manually (without Simulacrum), //it overrides Bladeburner stuff if (!this.hasSimulacrum() && this.ns.isBusy()) { this.ns.print("Idling bc player is busy with some other action"); diff --git a/doc/source/netscript/netscriptfunctions.rst b/doc/source/netscript/netscriptfunctions.rst index d0cb3ce37..deea623f9 100644 --- a/doc/source/netscript/netscriptfunctions.rst +++ b/doc/source/netscript/netscriptfunctions.rst @@ -54,7 +54,8 @@ This includes information such as function signatures, what they do, and their r getServerMinSecurityLevel() getServerRequiredHackingLevel() getServerNumPortsRequired() - getServerRam() + getServerMaxRam() + getServerUsedRam() serverExists() fileExists() isRunning() @@ -90,3 +91,8 @@ This includes information such as function signatures, what they do, and their r wget() getFavorToDonate() flags() + +.. toctree:: + :caption: Deprecated: + + getServerRam() \ No newline at end of file diff --git a/doc/source/netscript/netscripthacknetnodeapi.rst b/doc/source/netscript/netscripthacknetnodeapi.rst index 075633cf4..25b09b4b7 100644 --- a/doc/source/netscript/netscripthacknetnodeapi.rst +++ b/doc/source/netscript/netscripthacknetnodeapi.rst @@ -86,7 +86,7 @@ The following is an example of one way a script can be used to automate the purchasing and upgrading of Hacknet Nodes. This script attempts to purchase Hacknet Nodes until the player has a total of 8. Then -it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 cores +it gradually upgrades those Node's to a minimum of level 80, 16 GB RAM, and 8 cores .. code:: javascript @@ -129,3 +129,16 @@ it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 c }; print("All nodes upgraded to 16GB RAM"); + + for (var i = 0; i < cnt; i++) { + while (hacknet.getNodeStats(i).cores < 8) { + var cost = hacknet.getCoreUpgradeCost(i, 1); + while (myMoney() < cost) { + print("Need $" + cost + " . Have $" + myMoney()); + sleep(3000); + } + res = hacknet.upgradeCore(i, 1); + }; + }; + + print("All nodes upgraded to 8 cores"); diff --git a/index.html b/index.html index f09efe1da..65a1cdad5 100644 --- a/index.html +++ b/index.html @@ -327,8 +327,8 @@ Would you like to join?

Warning: Joining this faction may prevent you from joining other factions during this run!

- - + + diff --git a/package.json b/package.json index c424d5095..44b6b16ea 100644 --- a/package.json +++ b/package.json @@ -117,8 +117,8 @@ "build:dev": "webpack --mode development", "build:test": "webpack --config webpack.config-test.js", "lint": "npm run lint:jsts & npm run lint:style", - "lint:jsts": "eslint '*.{js,jsx,ts,tsx}' './src/**/*.{js,jsx,ts,tsx}' './test/**/*.{js,jsx,ts,tsx}' './utils/**/*.{js,jsx,ts,tsx}'", - "lint:style": "stylelint ./css/*", + "lint:jsts": "eslint --fix '*.{js,jsx,ts,tsx}' './src/**/*.{js,jsx,ts,tsx}' './test/**/*.{js,jsx,ts,tsx}' './utils/**/*.{js,jsx,ts,tsx}'", + "lint:style": "stylelint --fix ./css/*", "preinstall": "node ./scripts/engines-check.js", "test": "mochapack --webpack-config webpack.config-test.js -r jsdom-global/register ./test/index.js", "watch": "webpack --watch --mode production", diff --git a/src/Alias.ts b/src/Alias.ts index 5d1b11357..91c5dd96d 100644 --- a/src/Alias.ts +++ b/src/Alias.ts @@ -22,12 +22,12 @@ export function loadGlobalAliases(saveString: string): void { // Prints all aliases to terminal export function printAliases(): void { - for (var name in Aliases) { + for (const name in Aliases) { if (Aliases.hasOwnProperty(name)) { post("alias " + name + "=" + Aliases[name]); } } - for (var name in GlobalAliases) { + for (const name in GlobalAliases) { if (GlobalAliases.hasOwnProperty(name)) { post("global alias " + name + "=" + GlobalAliases[name]); } @@ -36,8 +36,8 @@ export function printAliases(): void { // Returns true if successful, false otherwise export function parseAliasDeclaration(dec: string, global = false): boolean { - var re = /^([_|\w|!|%|,|@]+)="(.+)"$/; - var matches = dec.match(re); + const re = /^([_|\w|!|%|,|@]+)="(.+)"$/; + const matches = dec.match(re); if (matches == null || matches.length != 3) {return false;} if (global){ addGlobalAlias(matches[1],matches[2]); @@ -100,17 +100,17 @@ export function substituteAliases(origCommand: string): string { // For the unalias command, dont substite if (commandArray[0] === "unalias") { return commandArray.join(" "); } - var alias = getAlias(commandArray[0]); + const alias = getAlias(commandArray[0]); if (alias != null) { commandArray[0] = alias; } else { - var alias = getGlobalAlias(commandArray[0]); + const alias = getGlobalAlias(commandArray[0]); if (alias != null) { commandArray[0] = alias; } } - for (var i = 0; i < commandArray.length; ++i) { - var alias = getGlobalAlias(commandArray[i]); + for (let i = 0; i < commandArray.length; ++i) { + const alias = getGlobalAlias(commandArray[i]); if (alias != null) { commandArray[i] = alias; } diff --git a/src/Augmentation/Augmentation.ts b/src/Augmentation/Augmentation.ts index 509a61475..283265fae 100644 --- a/src/Augmentation/Augmentation.ts +++ b/src/Augmentation/Augmentation.ts @@ -9,7 +9,7 @@ import { Factions } from "../Faction/Factions"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; interface IConstructorParams { - info: string; + info: string | JSX.Element; isSpecial?: boolean; moneyCost: number; name: string; @@ -49,31 +49,27 @@ interface IConstructorParams { } export class Augmentation { - // Initiatizes a Augmentation object from a JSON save state. - static fromJSON(value: any): Augmentation { - return Generic_fromJSON(Augmentation, value.data); - } // How much money this costs to buy - baseCost: number = 0; + baseCost = 0; // How much faction reputation is required to unlock this - baseRepRequirement: number = 0; + baseRepRequirement = 0; // Description of what this Aug is and what it does - info: string = ""; + info: string | JSX.Element; // Any Augmentation not immediately available in BitNode-1 is special (e.g. Bladeburner augs) - isSpecial: boolean = false; + isSpecial = false; // Augmentation level - for repeatable Augs like NeuroFlux Governor - level: number = 0; + level = 0; // Name of Augmentation - name: string = ""; + name = ""; // Whether the player owns this Augmentation - owned: boolean = false; + owned = false; // Array of names of all prerequisites prereqs: string[] = []; @@ -83,7 +79,7 @@ export class Augmentation { mults: IMap = {} // Initial cost. Doesn't change when you purchase multiple Augmentation - startingCost: number = 0; + startingCost = 0; constructor(params: IConstructorParams={ info: "", moneyCost: 0, name: "", repCost: 0 }) { this.name = params.name; @@ -141,7 +137,7 @@ export class Augmentation { console.warn(`In Augmentation.addToFactions(), could not find faction with this name: ${factionList[i]}`); continue; } - faction!.augmentations.push(this.name); + faction.augmentations.push(this.name); } } @@ -154,7 +150,7 @@ export class Augmentation { console.warn(`Invalid Faction object in addToAllFactions(). Key value: ${fac}`); continue; } - facObj!.augmentations.push(this.name); + facObj.augmentations.push(this.name); } } } @@ -163,6 +159,12 @@ export class Augmentation { toJSON(): any { return Generic_toJSON("Augmentation", this); } + + // Initiatizes a Augmentation object from a JSON save state. + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Augmentation { + return Generic_fromJSON(Augmentation, value.data); + } } Reviver.constructors.Augmentation = Augmentation; diff --git a/src/Augmentation/AugmentationHelpers.jsx b/src/Augmentation/AugmentationHelpers.jsx index f1dc2243d..30cf40e00 100644 --- a/src/Augmentation/AugmentationHelpers.jsx +++ b/src/Augmentation/AugmentationHelpers.jsx @@ -8,29 +8,13 @@ import { AugmentationsRoot } from "./ui/Root"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { CONSTANTS } from "../Constants"; import { Factions, factionExists } from "../Faction/Factions"; -import { startWorkerScript } from "../NetscriptWorker"; import { Player } from "../Player"; import { prestigeAugmentation } from "../Prestige"; import { saveObject } from "../SaveObject"; -import { RunningScript } from "../Script/RunningScript"; -import { Script } from "../Script/Script"; -import { Server } from "../Server/Server"; -import { OwnedAugmentationsOrderSetting } from "../Settings/SettingEnums"; -import { Settings } from "../Settings/Settings"; import { Page, routing } from "../ui/navigationTracking"; import { dialogBoxCreate } from "../../utils/DialogBox"; -import { createAccordionElement } from "../../utils/uiHelpers/createAccordionElement"; -import { - Reviver, - Generic_toJSON, - Generic_fromJSON -} from "../../utils/JSONReviver"; -import { formatNumber } from "../../utils/StringHelperFunctions"; import { clearObject } from "../../utils/helpers/clearObject"; -import { createElement } from "../../utils/uiHelpers/createElement"; -import { isString } from "../../utils/helpers/isString"; -import { removeChildrenFromElement } from "../../utils/uiHelpers/removeChildrenFromElement"; import { Money } from "../ui/React/Money"; import React from "react"; @@ -76,7 +60,7 @@ function initAugmentations() { "This augmentation increases the player's dexterity by 10%.", dexterity_mult: 1.1, }); - Targeting1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima", + Targeting1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Sector-12", "Ishima", "OmniTek Incorporated", "KuaiGong International", "Blade Industries"]); if (augmentationExists(AugmentationNames.Targeting1)) { delete Augmentations[AugmentationNames.Targeting1]; @@ -91,7 +75,7 @@ function initAugmentations() { prereqs:[AugmentationNames.Targeting1], dexterity_mult: 1.2, }); - Targeting2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima", + Targeting2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12", "OmniTek Incorporated", "KuaiGong International", "Blade Industries"]); if (augmentationExists(AugmentationNames.Targeting2)) { delete Augmentations[AugmentationNames.Targeting2]; @@ -152,7 +136,7 @@ function initAugmentations() { strength_mult: 1.1, defense_mult: 1.1, }); - CombatRib1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima", + CombatRib1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Volhaven", "Ishima", "OmniTek Incorporated", "KuaiGong International", "Blade Industries"]); if (augmentationExists(AugmentationNames.CombatRib1)) { delete Augmentations[AugmentationNames.CombatRib1]; @@ -168,7 +152,7 @@ function initAugmentations() { strength_mult: 1.14, defense_mult: 1.14, }); - CombatRib2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima", + CombatRib2.addToFactions(["The Dark Army", "The Syndicate", "Volhaven", "OmniTek Incorporated", "KuaiGong International", "Blade Industries"]); if (augmentationExists(AugmentationNames.CombatRib2)) { delete Augmentations[AugmentationNames.CombatRib2]; @@ -404,7 +388,7 @@ function initAugmentations() { info:"The body is injected with a chemical that artificially induces synaptic potentiation, " + "otherwise known as the strengthening of synapses. This results in a enhanced cognitive abilities.

" + "This augmentation:
" + - "Increases the player's hacking speed by 2%
" + + "Increases the player's hacking speed by 2%.
" + "Increases the player's hacking chance by 5%.
" + "Increases the player's hacking experience gain rate by 5%.", hacking_speed_mult: 1.02, @@ -444,7 +428,7 @@ function initAugmentations() { "This augmentation increases the player's hacking speed by 3%.", hacking_speed_mult: 1.03, }); - SynapticEnhancement.addToFactions(["CyberSec"]); + SynapticEnhancement.addToFactions(["CyberSec", "Aevum"]); if (augmentationExists(AugmentationNames.SynapticEnhancement)) { delete Augmentations[AugmentationNames.SynapticEnhancement]; } @@ -772,7 +756,7 @@ function initAugmentations() { "when working for a company by 20%.", company_rep_mult: 1.2, }); - NuoptimalInjectorImplant.addToFactions(["Tian Di Hui", "Volhaven", "New Tokyo", "Chongqing", "Ishima", + NuoptimalInjectorImplant.addToFactions(["Tian Di Hui", "Volhaven", "New Tokyo", "Chongqing", "Clarke Incorporated", "Four Sigma", "Bachman & Associates"]); if (augmentationExists(AugmentationNames.NuoptimalInjectorImplant)) { delete Augmentations[AugmentationNames.NuoptimalInjectorImplant]; @@ -1080,7 +1064,7 @@ function initAugmentations() { agility_exp_mult: 1.1, charisma_exp_mult: 1.1, }); - Neurotrainer1.addToFactions(["CyberSec"]); + Neurotrainer1.addToFactions(["CyberSec", "Aevum"]); if (augmentationExists(AugmentationNames.Neurotrainer1)) { delete Augmentations[AugmentationNames.Neurotrainer1]; } @@ -1256,7 +1240,7 @@ function initAugmentations() { // Daedalus const RedPill = new Augmentation({ name:AugmentationNames.TheRedPill, repCost:1e6, moneyCost:0, - info:"It's time to leave the cave." + info:"It's time to leave the cave.", }); RedPill.addToFactions(["Daedalus"]); if (augmentationExists(AugmentationNames.TheRedPill)) { @@ -1332,7 +1316,7 @@ function initAugmentations() { "capable of psychoanalyzing and profiling the personality of " + "others using optical imaging software.

" + "This augmentation:
" + - "Increases the player's charisma by 50%.
" + + "Increases the player's charisma by 50%.
" + "Increases the player's charisma experience gain rate by 50%.
" + "Increases the amount of reputation the player gains for a company by 25%.
" + "Increases the amount of reputation the player gains for a faction by 25%.", @@ -1556,7 +1540,7 @@ function initAugmentations() { and upload the assets.

This augmentation:
Lets the player start with {Money(1e6)} after a reset.
- Lets the player start with the BruteSSH.exe program after a reset. + Lets the player start with the BruteSSH.exe program after a reset., }); CashRoot.addToFactions(["Sector-12"]); if (augmentationExists(AugmentationNames.CashRoot)) { @@ -1743,7 +1727,7 @@ function initAugmentations() { "to induce wakefulness and concentration, suppress fear, reduce empathy, and " + "improve reflexes and memory-recall among other things.

" + "This augmentation:
" + - "Increases the player's sucess chance in Bladeburner contracts/operations by 3%.
" + + "Increases the player's success chance in Bladeburner contracts/operations by 3%.
" + "Increases the player's effectiveness in Bladeburner Field Analysis by 5%.
" + "Increases the player's Bladeburner stamina gain rate by 2%.", bladeburner_success_chance_mult: 1.03, @@ -2098,7 +2082,7 @@ export function displayAugmentationsContent(contentEl) { exportGameFn={saveObject.exportGame.bind(saveObject)} installAugmentationsFn={installAugmentations} />, - contentEl + contentEl, ); } diff --git a/src/Augmentation/Augmentations.ts b/src/Augmentation/Augmentations.ts index 229a17443..ed2eab639 100644 --- a/src/Augmentation/Augmentations.ts +++ b/src/Augmentation/Augmentations.ts @@ -1,4 +1,4 @@ import { Augmentation } from "./Augmentation"; import { IMap } from "../types"; -export let Augmentations: IMap = {}; +export const Augmentations: IMap = {}; diff --git a/src/Augmentation/PlayerOwnedAugmentation.ts b/src/Augmentation/PlayerOwnedAugmentation.ts index 2455c09f8..635c9f5b2 100644 --- a/src/Augmentation/PlayerOwnedAugmentation.ts +++ b/src/Augmentation/PlayerOwnedAugmentation.ts @@ -1,8 +1,8 @@ export class PlayerOwnedAugmentation { - level: number = 1; - name: string = ""; + level = 1; + name = ""; - constructor(name: string = "") { + constructor(name = "") { this.name = name; } } diff --git a/src/Augmentation/data/AugmentationNames.ts b/src/Augmentation/data/AugmentationNames.ts index ef8c6252c..2c681008d 100644 --- a/src/Augmentation/data/AugmentationNames.ts +++ b/src/Augmentation/data/AugmentationNames.ts @@ -1,6 +1,6 @@ import { IMap } from "../../types"; -export let AugmentationNames: IMap = { +export const AugmentationNames: IMap = { Targeting1: "Augmented Targeting I", Targeting2: "Augmented Targeting II", Targeting3: "Augmented Targeting III", diff --git a/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx b/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx index 35bf07ba8..a10783a49 100644 --- a/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx +++ b/src/Augmentation/ui/InstalledAugmentationsAndSourceFiles.tsx @@ -15,7 +15,9 @@ import { SourceFileMinus1 } from "./SourceFileMinus1"; import { Settings } from "../../Settings/Settings"; import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums"; -type IProps = {} +type IProps = { + // nothing special. +} type IState = { rerenderFlag: boolean; @@ -39,7 +41,7 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component { return { rerenderFlag: !prevState.rerenderFlag, @@ -79,17 +81,17 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component  {"=>"} , - {numeralWrapper.formatPercentage(r)} + {numeralWrapper.formatPercentage(r)}, ]; } return elems; @@ -51,38 +51,38 @@ export function PlayerMultipliers(): React.ReactElement { ['Hacking Chance ', Player.hacking_chance_mult, Player.hacking_chance_mult*mults.hacking_chance_mult], ['Hacking Speed ', Player.hacking_speed_mult, Player.hacking_speed_mult*mults.hacking_speed_mult], ['Hacking Money ', Player.hacking_money_mult, Player.hacking_money_mult*mults.hacking_money_mult], - ['Hacking Growth ', Player.hacking_grow_mult, Player.hacking_grow_mult*mults.hacking_grow_mult] + ['Hacking Growth ', Player.hacking_grow_mult, Player.hacking_grow_mult*mults.hacking_grow_mult], ])}
{MultiplierTable([ ['Hacking Level ', Player.hacking_mult, Player.hacking_mult*mults.hacking_mult], - ['Hacking Experience ', Player.hacking_exp_mult, Player.hacking_exp_mult*mults.hacking_exp_mult] + ['Hacking Experience ', Player.hacking_exp_mult, Player.hacking_exp_mult*mults.hacking_exp_mult], ])}
{MultiplierTable([ ['Strength Level ', Player.strength_mult, Player.strength_mult*mults.strength_mult], - ['Strength Experience ', Player.strength_exp_mult, Player.strength_exp_mult*mults.strength_exp_mult] + ['Strength Experience ', Player.strength_exp_mult, Player.strength_exp_mult*mults.strength_exp_mult], ])}
{MultiplierTable([ ['Defense Level ', Player.defense_mult, Player.defense_mult*mults.defense_mult], - ['Defense Experience ', Player.defense_exp_mult, Player.defense_exp_mult*mults.defense_exp_mult] + ['Defense Experience ', Player.defense_exp_mult, Player.defense_exp_mult*mults.defense_exp_mult], ])}
{MultiplierTable([ ['Dexterity Level ', Player.dexterity_mult, Player.dexterity_mult*mults.dexterity_mult], - ['Dexterity Experience ', Player.dexterity_exp_mult, Player.dexterity_exp_mult*mults.dexterity_exp_mult] + ['Dexterity Experience ', Player.dexterity_exp_mult, Player.dexterity_exp_mult*mults.dexterity_exp_mult], ])}
{MultiplierTable([ ['Agility Level ', Player.agility_mult, Player.agility_mult*mults.agility_mult], - ['Agility Experience ', Player.agility_exp_mult, Player.agility_exp_mult*mults.agility_exp_mult] + ['Agility Experience ', Player.agility_exp_mult, Player.agility_exp_mult*mults.agility_exp_mult], ])}
{MultiplierTable([ ['Charisma Level ', Player.charisma_mult, Player.charisma_mult*mults.charisma_mult], - ['Charisma Experience ', Player.charisma_exp_mult, Player.charisma_exp_mult*mults.charisma_exp_mult] + ['Charisma Experience ', Player.charisma_exp_mult, Player.charisma_exp_mult*mults.charisma_exp_mult], ])}
{MultiplierTable([ @@ -90,13 +90,13 @@ export function PlayerMultipliers(): React.ReactElement { ['Hacknet Node purchase cost ', Player.hacknet_node_purchase_cost_mult, Player.hacknet_node_purchase_cost_mult*mults.hacknet_node_purchase_cost_mult], ['Hacknet Node RAM upgrade cost ', Player.hacknet_node_ram_cost_mult, Player.hacknet_node_ram_cost_mult*mults.hacknet_node_ram_cost_mult], ['Hacknet Node Core purchase cost ', Player.hacknet_node_core_cost_mult, Player.hacknet_node_core_cost_mult*mults.hacknet_node_core_cost_mult], - ['Hacknet Node level upgrade cost ', Player.hacknet_node_level_cost_mult, Player.hacknet_node_level_cost_mult*mults.hacknet_node_level_cost_mult] + ['Hacknet Node level upgrade cost ', Player.hacknet_node_level_cost_mult, Player.hacknet_node_level_cost_mult*mults.hacknet_node_level_cost_mult], ])}
{MultiplierTable([ ['Company reputation gain ', Player.company_rep_mult, Player.company_rep_mult*mults.company_rep_mult], ['Faction reputation gain ', Player.faction_rep_mult, Player.faction_rep_mult*mults.faction_rep_mult], - ['Salary ', Player.work_money_mult, Player.work_money_mult*mults.work_money_mult] + ['Salary ', Player.work_money_mult, Player.work_money_mult*mults.work_money_mult], ])}
{MultiplierTable([ diff --git a/src/Augmentation/ui/PurchasedAugmentations.tsx b/src/Augmentation/ui/PurchasedAugmentations.tsx index 3bc54d837..ab0854e9a 100644 --- a/src/Augmentation/ui/PurchasedAugmentations.tsx +++ b/src/Augmentation/ui/PurchasedAugmentations.tsx @@ -22,7 +22,7 @@ export function PurchasedAugmentations(): React.ReactElement { augs.push(
  • -
  • + , ) } diff --git a/src/Augmentation/ui/Root.tsx b/src/Augmentation/ui/Root.tsx index 10e733556..d9350836c 100644 --- a/src/Augmentation/ui/Root.tsx +++ b/src/Augmentation/ui/Root.tsx @@ -25,7 +25,7 @@ export class AugmentationsRoot extends React.Component { super(props); } - render() { + render(): React.ReactNode { return (

    Purchased Augmentations

    diff --git a/src/Augmentation/ui/SourceFileMinus1.tsx b/src/Augmentation/ui/SourceFileMinus1.tsx index b97bcbf40..817c3250f 100644 --- a/src/Augmentation/ui/SourceFileMinus1.tsx +++ b/src/Augmentation/ui/SourceFileMinus1.tsx @@ -5,15 +5,12 @@ import * as React from "react"; import { Player } from "../../Player"; -import { Settings } from "../../Settings/Settings"; -import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums"; -import { SourceFiles } from "../../SourceFile/SourceFiles"; import { Exploit, ExploitName } from "../../Exploits/Exploit"; import { Accordion } from "../../ui/React/Accordion"; export function SourceFileMinus1(): React.ReactElement { - let exploits = Player.exploits; + const exploits = Player.exploits; if(exploits.length === 0) { return <> diff --git a/src/BitNode/BitNode.ts b/src/BitNode/BitNode.ts index 42d937351..67adcc3c9 100644 --- a/src/BitNode/BitNode.ts +++ b/src/BitNode/BitNode.ts @@ -16,7 +16,7 @@ class BitNode { number: number; - constructor(n: number, name: string, desc: string="", info: string="") { + constructor(n: number, name: string, desc="", info="") { this.number = n; this.name = name; this.desc = desc; @@ -236,8 +236,7 @@ BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.", "To iterate is human, to recurse divine.

    " + "Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Source-File 12, or " + "if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " + - "of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " + - "In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)"); + "of Source-File 12 lets you start any BitNodes with NeuroFlux Governor equal to the level of this source file."); // Books: Frontera, Shiner BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON"); @@ -252,11 +251,11 @@ BitNodes["BitNode22"] = new BitNode(22, "", "COMING SOON"); BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON"); BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON"); -export function initBitNodeMultipliers(p: IPlayer) { +export function initBitNodeMultipliers(p: IPlayer): void { if (p.bitNodeN == null) { p.bitNodeN = 1; } - for (var mult in BitNodeMultipliers) { + for (const mult in BitNodeMultipliers) { if (BitNodeMultipliers.hasOwnProperty(mult)) { BitNodeMultipliers[mult] = 1; } @@ -433,15 +432,15 @@ export function initBitNodeMultipliers(p: IPlayer) { BitNodeMultipliers.FourSigmaMarketDataCost = 4; BitNodeMultipliers.FourSigmaMarketDataApiCost = 4; break; - case 12: //The Recursion - var sf12Lvl = 0; - for (var i = 0; i < p.sourceFiles.length; i++) { + case 12: { //The Recursion + let sf12Lvl = 0; + for (let i = 0; i < p.sourceFiles.length; i++) { if (p.sourceFiles[i].n === 12) { sf12Lvl = p.sourceFiles[i].lvl; } } - var inc = Math.pow(1.02, sf12Lvl); - var dec = 1/inc; + const inc = Math.pow(1.02, sf12Lvl); + const dec = 1/inc; // Multiplier for number of augs needed for Daedalus increases // up to a maximum of 1.34, which results in 40 Augs required @@ -499,6 +498,7 @@ export function initBitNodeMultipliers(p: IPlayer) { BitNodeMultipliers.BladeburnerRank = dec; BitNodeMultipliers.BladeburnerSkillCost = inc; break; + } default: console.warn("Player.bitNodeN invalid"); break; diff --git a/src/Bladeburner.jsx b/src/Bladeburner.jsx index 2808719e6..f786d5d96 100644 --- a/src/Bladeburner.jsx +++ b/src/Bladeburner.jsx @@ -1,7 +1,6 @@ import { Augmentations } from "./Augmentation/Augmentations"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers"; -import { CONSTANTS } from "./Constants"; import { Engine } from "./engine"; import { Faction } from "./Faction/Faction"; import { Factions, factionExists } from "./Faction/Factions"; @@ -17,17 +16,19 @@ import { dialogBoxCreate } from "../utils/DialogBox"; import { Reviver, Generic_toJSON, - Generic_fromJSON + Generic_fromJSON, } from "../utils/JSONReviver"; import { setTimeoutRef } from "./utils/SetTimeoutRef"; -import { formatNumber } from "../utils/StringHelperFunctions"; +import { + formatNumber, + convertTimeMsToTimeElapsedString, +} from "../utils/StringHelperFunctions"; import { ConsoleHelpText } from "./Bladeburner/data/Help"; import { City } from "./Bladeburner/City"; import { BladeburnerConstants } from "./Bladeburner/data/Constants"; import { Skill } from "./Bladeburner/Skill"; import { Skills } from "./Bladeburner/Skills"; -import { SkillNames } from "./Bladeburner/data/SkillNames"; import { Operation } from "./Bladeburner/Operation"; import { BlackOperation } from "./Bladeburner/BlackOperation"; import { BlackOperations } from "./Bladeburner/BlackOperations"; @@ -45,7 +46,6 @@ import { KEY } from "../utils/helpers/keyCodes"; import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement"; import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks"; -import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; import { createElement } from "../utils/uiHelpers/createElement"; import { createPopup } from "../utils/uiHelpers/createPopup"; import { removeElement } from "../utils/uiHelpers/removeElement"; @@ -236,7 +236,7 @@ Bladeburner.prototype.create = function() { count:getRandomInt(25, 150), countGrowth:getRandomInt(5, 75)/10, weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1}, - isStealth:true + isStealth:true, }); this.contracts["Bounty Hunter"] = new Contract({ name:"Bounty Hunter", @@ -248,7 +248,7 @@ Bladeburner.prototype.create = function() { count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10, weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, - isKill:true + isKill:true, }); this.contracts["Retirement"] = new Contract({ name:"Retirement", @@ -260,7 +260,7 @@ Bladeburner.prototype.create = function() { count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10, weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, - isKill:true + isKill:true, }); this.operations["Investigation"] = new Operation({ @@ -275,7 +275,7 @@ Bladeburner.prototype.create = function() { count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10, weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1}, decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, - isStealth:true + isStealth:true, }); this.operations["Undercover Operation"] = new Operation({ name:"Undercover Operation", @@ -288,7 +288,7 @@ Bladeburner.prototype.create = function() { count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10, weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1}, decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, - isStealth:true + isStealth:true, }); this.operations["Sting Operation"] = new Operation({ name:"Sting Operation", @@ -299,19 +299,19 @@ Bladeburner.prototype.create = function() { count:getRandomInt(1, 150), countGrowth:getRandomInt(3, 40)/10, weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1}, decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9}, - isStealth:true + isStealth:true, }); this.operations["Raid"] = new Operation({ name:"Raid", desc:"Lead an assault on a known Synthoid community. Note that " + "there must be an existing Synthoid community in your current city " + - "in order for this Operation to be successful", + "in order for this Operation to be successful.", baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000, rankGain:55,rankLoss:2.5,hpLoss:50, count:getRandomInt(1, 150), countGrowth:getRandomInt(2, 40)/10, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, - isKill:true + isKill:true, }); this.operations["Stealth Retirement Operation"] = new Operation({ name:"Stealth Retirement Operation", @@ -323,7 +323,7 @@ Bladeburner.prototype.create = function() { count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, - isStealth:true, isKill:true + isStealth:true, isKill:true, }); this.operations["Assassination"] = new Operation({ name:"Assassination", @@ -335,7 +335,7 @@ Bladeburner.prototype.create = function() { count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8}, - isStealth:true, isKill:true + isStealth:true, isKill:true, }); } @@ -1271,7 +1271,7 @@ Bladeburner.prototype.createContent = function() { DomElems.consoleInput.focus(); } return false; - } + }, }); DomElems.consoleTable = createElement("table", {class:"bladeburner-console-table"}); DomElems.consoleInputRow = createElement("tr", {class:"bladeburner-console-input-row", id:"bladeburner-console-input-row"}); @@ -1279,7 +1279,7 @@ Bladeburner.prototype.createContent = function() { DomElems.consoleInputHeader = createElement("pre", {innerText:"> "}); DomElems.consoleInput = createElement("input", { type:"text", class:"bladeburner-console-input", tabIndex:1, - onfocus:() => {DomElems.consoleInput.value = DomElems.consoleInput.value} + onfocus:() => {DomElems.consoleInput.value = DomElems.consoleInput.value}, }); DomElems.consoleInputCell.appendChild(DomElems.consoleInputHeader); @@ -1363,7 +1363,7 @@ Bladeburner.prototype.createOverviewContent = function() { innerText:"Est. Synthoid Population: ", display:"inline-block", tooltip:"This is your Bladeburner division's estimate of how many Synthoids exist " + - "in your current city." + "in your current city.", }); DomElems.overviewEstPopHelpTip = createElement("div", { @@ -1381,7 +1381,7 @@ Bladeburner.prototype.createOverviewContent = function() { "The Synthoid populations of cities can change due to your " + "actions or random events. If random events occur, they will " + "be logged in the Bladeburner Console."); - } + }, }); DomElems.overviewEstComms = createElement("p", { @@ -1395,14 +1395,14 @@ Bladeburner.prototype.createOverviewContent = function() { innerText:"City Chaos: ", display:"inline-block", tooltip:"The city's chaos level due to tensions and conflicts between humans and Synthoids. " + - "Having too high of a chaos level can make contracts and operations harder." + "Having too high of a chaos level can make contracts and operations harder.", }); DomElems.overviewBonusTime = createElement("p", { innerText: "Bonus time: ", display: "inline-block", tooltip: "You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by browser). " + - "Bonus time makes the Bladeburner mechanic progress faster, up to 5x the normal speed." + "Bonus time makes the Bladeburner mechanic progress faster, up to 5x the normal speed.", }); DomElems.overviewSkillPoints = createElement("p", {display:"block"}); @@ -1438,7 +1438,7 @@ Bladeburner.prototype.createOverviewContent = function() { innerText:"Cancel", class:"a-link-button", clickListener:() => { removeElementById(popupId); return false; - } + }, })) popupArguments.push(createElement("p", { // Info Text innerText:"Travel to a different city for your Bladeburner " + @@ -1460,12 +1460,12 @@ Bladeburner.prototype.createOverviewContent = function() { removeElementById(popupId); inst.updateOverviewContent(); return false; - } + }, })); })(this, i); } createPopup(popupId, popupArguments); - } + }, })); // Faction button @@ -1493,7 +1493,7 @@ Bladeburner.prototype.createOverviewContent = function() { } } return false; - } + }, })); } @@ -1526,14 +1526,14 @@ Bladeburner.prototype.createActionAndSkillsContent = function() { DomElems.currentTab = buttons[i].toLowerCase(); inst.createActionAndSkillsContent(); return false; - } + }, })); }) (buttons, i, this, currTab); } // General info/description for each action DomElems.actionsAndSkillsDesc = createElement("p", { - display:"block", margin:"4px", padding:"4px" + display:"block", margin:"4px", padding:"4px", }); // List for actions/skills @@ -1578,7 +1578,7 @@ Bladeburner.prototype.createGeneralActionsContent = function() { for (var actionName in GeneralActions) { if (GeneralActions.hasOwnProperty(actionName)) { DomElems.generalActions[actionName] = createElement("div", { - class:"bladeburner-action", name:actionName + class:"bladeburner-action", name:actionName, }); DomElems.actionsAndSkillsList.appendChild(DomElems.generalActions[actionName]); } @@ -1600,7 +1600,7 @@ Bladeburner.prototype.createContractsContent = function() { for (var contractName in this.contracts) { if (this.contracts.hasOwnProperty(contractName)) { DomElems.contracts[contractName] = createElement("div", { - class:"bladeburner-action", name:contractName + class:"bladeburner-action", name:contractName, }); DomElems.actionsAndSkillsList.appendChild(DomElems.contracts[contractName]); } @@ -1629,7 +1629,7 @@ Bladeburner.prototype.createOperationsContent = function() { for (var operationName in this.operations) { if (this.operations.hasOwnProperty(operationName)) { DomElems.operations[operationName] = createElement("div", { - class:"bladeburner-action", name:operationName + class:"bladeburner-action", name:operationName, }); DomElems.actionsAndSkillsList.appendChild(DomElems.operations[operationName]); } @@ -1667,7 +1667,7 @@ Bladeburner.prototype.createBlackOpsContent = function() { for (var i = blackops.length-1; i >= 0 ; --i) { if (this.blackops[[blackops[i].name]] == null && i !== 0 && this.blackops[[blackops[i-1].name]] == null) {continue;} // If this one nor the next are completed then this isn't unlocked yet. DomElems.blackops[blackops[i].name] = createElement("div", { - class:"bladeburner-action", name:blackops[i].name + class:"bladeburner-action", name:blackops[i].name, }); DomElems.actionsAndSkillsList.appendChild(DomElems.blackops[blackops[i].name]); } @@ -1750,7 +1750,7 @@ Bladeburner.prototype.createSkillsContent = function() { // Skill Points DomElems.skillPointsDisplay = createElement("p", { - innerHTML:"
    Skill Points: " + formatNumber(this.skillPoints, 0) + "" + innerHTML:"
    Skill Points: " + formatNumber(this.skillPoints, 0) + "", }); DomElems.actionAndSkillsDiv.appendChild(DomElems.skillPointsDisplay); @@ -1758,7 +1758,7 @@ Bladeburner.prototype.createSkillsContent = function() { for (var skillName in Skills) { if (Skills.hasOwnProperty(skillName)) { DomElems.skills[skillName] = createElement("div", { - class:"bladeburner-action", name:skillName + class:"bladeburner-action", name:skillName, }); DomElems.actionsAndSkillsList.appendChild(DomElems.skills[skillName]); } @@ -1902,7 +1902,7 @@ Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) { var progress = this.actionTimeCurrent / this.actionTimeToComplete; el.appendChild(createElement("p", { display:"block", - innerText:createProgressBarText({progress:progress}) + innerText:createProgressBarText({progress:progress}), })); } else { // Start button @@ -1915,13 +1915,13 @@ Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) { this.startAction(this.action); this.updateActionAndSkillsContent(); return false; - } + }, })); } appendLineBreaks(el, 2); el.appendChild(createElement("pre", { // Info - innerHTML:action.desc, display:"inline-block" + innerHTML:action.desc, display:"inline-block", })); @@ -1937,14 +1937,14 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) { formatNumber(this.actionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeToComplete, 0) + ")" : action.name, - display:"inline-block" + display:"inline-block", })); if (isActive) { // Progress bar if its active var progress = this.actionTimeCurrent / this.actionTimeToComplete; el.appendChild(createElement("p", { display:"block", - innerText:createProgressBarText({progress:progress}) + innerText:createProgressBarText({progress:progress}), })); } else { // Start button el.appendChild(createElement("a", { @@ -1956,7 +1956,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) { this.startAction(this.action); this.updateActionAndSkillsContent(); return false; - } + }, })); } @@ -1967,7 +1967,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) { display:"inline-block", innerText:"Level: " + action.level + " / " + action.maxLevel, tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.ContractSuccessesPerLevel) + " successes " + - "needed for next level" + "needed for next level", })); el.appendChild(createElement("a", { class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"↑", @@ -1979,7 +1979,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) { if (isActive) {this.startAction(this.action);} // Restart Action this.updateContractsUIElement(el, action); return false; - } + }, })); el.appendChild(createElement("a", { class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"↓", @@ -1991,7 +1991,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) { if (isActive) {this.startAction(this.action);} // Restart Action this.updateContractsUIElement(el, action); return false; - } + }, })); var actionTime = action.getActionTime(this); @@ -2011,7 +2011,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) { var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox"; el.appendChild(createElement("label", { for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white", - tooltip:"Automatically increase contract level when possible" + tooltip:"Automatically increase contract level when possible", })); const checkboxInput = createElement("input", { @@ -2035,14 +2035,14 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { formatNumber(this.actionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeToComplete, 0) + ")" : action.name, - display:"inline-block" + display:"inline-block", })); if (isActive) { // Progress bar if its active var progress = this.actionTimeCurrent / this.actionTimeToComplete; el.appendChild(createElement("p", { display:"block", - innerText:createProgressBarText({progress:progress}) + innerText:createProgressBarText({progress:progress}), })); } else { // Start button and set Team Size button el.appendChild(createElement("a", { @@ -2054,7 +2054,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { this.startAction(this.action); this.updateActionAndSkillsContent(); return false; - } + }, })); el.appendChild(createElement("a", { innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button", @@ -2065,7 +2065,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { innerText:"Enter the amount of team members you would like to take on these " + "operations. If you do not have the specified number of team members, " + "then as many as possible will be used. Note that team members may " + - "be lost during operations." + "be lost during operations.", }); var input = createElement("input", { @@ -2083,17 +2083,17 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { } removeElementById(popupId); return false; - } + }, }); var cancelBtn = createElement("a", { innerText:"Cancel", class:"a-link-button", clickListener:() => { removeElementById(popupId); return false; - } + }, }); createPopup(popupId, [txt, input, setBtn, cancelBtn]); - } + }, })); } @@ -2104,7 +2104,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { display:"inline-block", innerText:"Level: " + action.level + " / " + action.maxLevel, tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.OperationSuccessesPerLevel) + " successes " + - "needed for next level" + "needed for next level", })); el.appendChild(createElement("a", { class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"↑", @@ -2116,7 +2116,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { if (isActive) {this.startAction(this.action);} // Restart Action this.updateOperationsUIElement(el, action); return false; - } + }, })); el.appendChild(createElement("a", { class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"↓", @@ -2128,11 +2128,10 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { if (isActive) {this.startAction(this.action);} // Restart Action this.updateOperationsUIElement(el, action); return false; - } + }, })); // General Info - var difficulty = action.getDifficulty(); var actionTime = action.getActionTime(this); appendLineBreaks(el, 2); el.appendChild(createElement("pre", { @@ -2150,7 +2149,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) { var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox"; el.appendChild(createElement("label", { for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white", - tooltip:"Automatically increase operation level when possible" + tooltip:"Automatically increase operation level when possible", })); const checkboxInput = createElement("input", { @@ -2170,7 +2169,6 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) { var isActive = el.classList.contains(ActiveActionCssClass); var isCompleted = (this.blackops[action.name] != null); var estimatedSuccessChance = action.getSuccessChance(this, {est:true}); - var difficulty = action.getDifficulty(); var actionTime = action.getActionTime(this); var hasReqdRank = this.rank >= action.reqdRank; @@ -2194,7 +2192,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) { var progress = this.actionTimeCurrent / this.actionTimeToComplete; el.appendChild(createElement("p", { display:"block", - innerText:createProgressBarText({progress:progress}) + innerText:createProgressBarText({progress:progress}), })); } else { el.appendChild(createElement("a", { // Start button @@ -2206,7 +2204,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) { this.startAction(this.action); this.updateActionAndSkillsContent(); return false; - } + }, })); el.appendChild(createElement("a", { // Set Team Size Button innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button", @@ -2217,7 +2215,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) { innerText:"Enter the amount of team members you would like to take on this " + "BlackOp. If you do not have the specified number of team members, " + "then as many as possible will be used. Note that team members may " + - "be lost during operations." + "be lost during operations.", }); var input = createElement("input", { @@ -2235,17 +2233,17 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) { } removeElementById(popupId); return false; - } + }, }); var cancelBtn = createElement("a", { innerText:"Cancel", class:"a-link-button", clickListener:() => { removeElementById(popupId); return false; - } + }, }); createPopup(popupId, [txt, input, setBtn, cancelBtn]); - } + }, })); } @@ -2257,7 +2255,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) { })); el.appendChild(createElement("p", { display:"block", color:hasReqdRank ? "white" : "red", - innerHTML:"Required Rank: " + formatNumber(action.reqdRank, 0) + "
    " + innerHTML:"Required Rank: " + formatNumber(action.reqdRank, 0) + "
    ", })); el.appendChild(createElement("p", { display:"inline-block", @@ -2297,7 +2295,7 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) { this.upgradeSkill(skill); this.createActionAndSkillsContent(); return false; - } + }, })); appendLineBreaks(el, 2); el.appendChild(createElement("p", { @@ -2307,7 +2305,7 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) { if (maxLvl) { el.appendChild(createElement("p", { color:"red", display:"block", - innerText:"MAX LEVEL" + innerText:"MAX LEVEL", })); } else { el.appendChild(createElement("p", { @@ -2508,7 +2506,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) { case "gen": if (GeneralActions[val] != null) { var action = new ActionIdentifier({ - type:ActionTypes[val], name:val + type:ActionTypes[val], name:val, }); if (highLow) { this.automateActionHigh = action; @@ -2524,7 +2522,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) { case "contracts": if (this.contracts[val] != null) { var action = new ActionIdentifier({ - type:ActionTypes.Contract, name:val + type:ActionTypes.Contract, name:val, }); if (highLow) { this.automateActionHigh = action; @@ -2542,7 +2540,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) { case "operation": if (this.operations[val] != null) { var action = new ActionIdentifier({ - type:ActionTypes.Operation, name:val + type:ActionTypes.Operation, name:val, }); if (highLow) { this.automateActionHigh = action; @@ -3210,7 +3208,7 @@ Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, worker return -1; } - const sanitizedSize = Math.round(size); + let sanitizedSize = Math.round(size); if (isNaN(sanitizedSize) || sanitizedSize < 0) { workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`); return -1; diff --git a/src/Bladeburner/Action.ts b/src/Bladeburner/Action.ts index d2b78a011..e4e42d749 100644 --- a/src/Bladeburner/Action.ts +++ b/src/Bladeburner/Action.ts @@ -3,21 +3,20 @@ import { getRandomInt } from "../../utils/helpers/getRandomInt"; import { addOffset } from "../../utils/helpers/addOffset"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { BladeburnerConstants } from "./data/Constants"; -// import { Contract } from "./Contract"; -// import { Operation } from "./Operation"; -// import { BlackOperation } from "./BlackOperation"; +import { IBladeburner } from "./IBladeburner"; +import { IAction, ISuccessChanceParams } from "./IAction"; class StatsMultiplier { - hack: number = 0; - str: number = 0; - def: number = 0; - dex: number = 0; - agi: number = 0; - cha: number = 0; - int: number = 0; - [key: string]: number; -}; + + hack = 0; + str = 0; + def = 0; + dex = 0; + agi = 0; + cha = 0; + int = 0; +} export interface IActionParams { name?: string; @@ -43,32 +42,32 @@ export interface IActionParams { teamCount?: number; } -export class Action { - name: string = ""; - desc: string = ""; +export class Action implements IAction { + name = ""; + desc = ""; // Difficulty scales with level. See getDifficulty() method - level: number = 1; - maxLevel: number = 1; - autoLevel: boolean = true; - baseDifficulty: number = 100; - difficultyFac: number = 1.01; + level = 1; + maxLevel = 1; + autoLevel = true; + baseDifficulty = 100; + difficultyFac = 1.01; // Rank increase/decrease is affected by this exponent - rewardFac: number = 1.02; + rewardFac = 1.02; - successes: number = 0; - failures: number = 0; + successes = 0; + failures = 0; // All of these scale with level/difficulty - rankGain: number = 0; - rankLoss: number = 0; - hpLoss: number = 0; - hpLost: number = 0; + rankGain = 0; + rankLoss = 0; + hpLoss = 0; + hpLost = 0; // Action Category. Current categories are stealth and kill - isStealth: boolean = false; - isKill: boolean = false; + isStealth = false; + isKill = false; /** * Number of this contract remaining, and its growth rate @@ -81,7 +80,7 @@ export class Action { weights: StatsMultiplier = {hack:1/7,str:1/7,def:1/7,dex:1/7,agi:1/7,cha:1/7,int:1/7}; // Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1) decays: StatsMultiplier = { hack: 0.9, str: 0.9, def: 0.9, dex: 0.9, agi: 0.9, cha: 0.9, int: 0.9 }; - teamCount: number = 0; + teamCount = 0; // Base Class for Contracts, Operations, and BlackOps constructor(params: IActionParams| null = null) { // | null = null @@ -138,7 +137,7 @@ export class Action { * Tests for success. Should be called when an action has completed * @param inst {Bladeburner} - Bladeburner instance */ - attempt(inst: any): boolean { + attempt(inst: IBladeburner): boolean { return (Math.random() < this.getSuccessChance(inst)); } @@ -147,7 +146,7 @@ export class Action { return 1; } - getActionTime(inst: any): number { + getActionTime(inst: IBladeburner): number { const difficulty = this.getDifficulty(); let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor; const skillFac = inst.skillMultipliers.actionTime; // Always < 1 @@ -165,15 +164,15 @@ export class Action { } // For actions that have teams. To be implemented by subtypes. - getTeamSuccessBonus(inst: any): number { + getTeamSuccessBonus(inst: IBladeburner): number { return 1; } - getActionTypeSkillSuccessBonus(inst: any): number { + getActionTypeSkillSuccessBonus(inst: IBladeburner): number { return 1; } - getChaosCompetencePenalty(inst: any, params: any): number { + getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number { const city = inst.getCurrentCity(); if (params.est) { return Math.pow((city.popEst / BladeburnerConstants.PopulationThreshold), BladeburnerConstants.PopulationExponent); @@ -182,7 +181,7 @@ export class Action { } } - getChaosDifficultyBonus(inst: any, params: any): number { + getChaosDifficultyBonus(inst: IBladeburner/*, params: ISuccessChanceParams*/): number { const city = inst.getCurrentCity(); if (city.chaos > BladeburnerConstants.ChaosThreshold) { const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold); @@ -198,14 +197,14 @@ export class Action { * @params - options: * est (bool): Get success chance estimate instead of real success chance */ - getSuccessChance(inst: any, params: any={}) { + getSuccessChance(inst: IBladeburner, params: ISuccessChanceParams={est: false}): number { if (inst == null) {throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance");} let difficulty = this.getDifficulty(); let competence = 0; - for (let stat in this.weights) { + for (const stat in this.weights) { if (this.weights.hasOwnProperty(stat)) { - let playerStatLvl = Player.queryStatFromString(stat); - let key = "eff" + stat.charAt(0).toUpperCase() + stat.slice(1); + const playerStatLvl = Player.queryStatFromString(stat); + const key = "eff" + stat.charAt(0).toUpperCase() + stat.slice(1); let effMultiplier = inst.skillMultipliers[key]; if (effMultiplier == null) { console.error(`Failed to find Bladeburner Skill multiplier for: ${stat}`); @@ -220,7 +219,7 @@ export class Action { competence *= this.getTeamSuccessBonus(inst); competence *= this.getChaosCompetencePenalty(inst, params); - difficulty *= this.getChaosDifficultyBonus(inst, params); + difficulty *= this.getChaosDifficultyBonus(inst); if(this.name == "Raid" && inst.getCurrentCity().comms <= 0) { return 0; @@ -253,18 +252,14 @@ export class Action { } } - static fromJSON(value: any): Action { - return Generic_fromJSON(Action, value.data); - } - toJSON(): any { return Generic_toJSON("Action", this); } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Action { + return Generic_fromJSON(Action, value.data); + } } - - - - - Reviver.constructors.Action = Action; \ No newline at end of file diff --git a/src/Bladeburner/BlackOperation.ts b/src/Bladeburner/BlackOperation.ts index 11ac83dc4..c5fbe1e07 100644 --- a/src/Bladeburner/BlackOperation.ts +++ b/src/Bladeburner/BlackOperation.ts @@ -13,21 +13,22 @@ export class BlackOperation extends Operation { return 1.5; } - getChaosCompetencePenalty(inst: any, params: any): number { + getChaosCompetencePenalty(/*inst: IBladeburner, params: ISuccessChanceParams*/): number { return 1; } - getChaosDifficultyBonus(inst: any, params: any): number { + getChaosDifficultyBonus(/*inst: IBladeburner, params: ISuccessChanceParams*/): number { return 1; } - static fromJSON(value: any): Operation { - return Generic_fromJSON(BlackOperation, value.data); - } - toJSON(): any { return Generic_toJSON("BlackOperation", this); } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Operation { + return Generic_fromJSON(BlackOperation, value.data); + } } Reviver.constructors.BlackOperation = BlackOperation; \ No newline at end of file diff --git a/src/Bladeburner/BlackOperations.ts b/src/Bladeburner/BlackOperations.ts index 94adc750c..cb75f91d4 100644 --- a/src/Bladeburner/BlackOperations.ts +++ b/src/Bladeburner/BlackOperations.ts @@ -16,7 +16,7 @@ export const BlackOperations: IMap = {}; rankGain:50, rankLoss:10, hpLoss:100, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Zero"] = new BlackOperation({ name:"Operation Zero", @@ -33,7 +33,7 @@ export const BlackOperations: IMap = {}; rankGain:60, rankLoss:15, hpLoss:50, weights:{hack:0.2,str:0.15,def:0.15,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isStealth:true + isStealth:true, }); BlackOperations["Operation X"] = new BlackOperation({ name:"Operation X", @@ -52,7 +52,7 @@ export const BlackOperations: IMap = {}; rankGain:75, rankLoss:15, hpLoss:100, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Titan"] = new BlackOperation({ name:"Operation Titan", @@ -70,7 +70,7 @@ export const BlackOperations: IMap = {}; rankGain:100, rankLoss:20, hpLoss:100, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Ares"] = new BlackOperation({ name:"Operation Ares", @@ -84,7 +84,7 @@ export const BlackOperations: IMap = {}; rankGain:125, rankLoss:20, hpLoss:200, weights:{hack:0,str:0.25,def:0.25,dex:0.25,agi:0.25,cha:0, int:0}, decays:{hack:0,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Archangel"] = new BlackOperation({ name:"Operation Archangel", @@ -152,7 +152,7 @@ export const BlackOperations: IMap = {}; rankGain:750, rankLoss:60, hpLoss:1000, weights:{hack:0.05,str:0.2,def:0.2,dex:0.25,agi:0.25,cha:0, int:0.05}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Deckard"] = new BlackOperation({ name:"Operation Deckard", @@ -160,7 +160,7 @@ export const BlackOperations: IMap = {}; "technology in Operation K, we've discovered that a small group of " + "MK-VI Synthoids were able to make off with the schematics and design " + "of the technology before the Operation. It is almost a certainty that " + - "these Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising." + + "these Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising.

    " + "The goal of Operation Deckard is to hunt down these Synthoids and retire " + "them. I don't need to tell you how critical this mission is.", baseDifficulty:20e3, reqdRank:40e3, @@ -202,7 +202,7 @@ export const BlackOperations: IMap = {}; rankGain:2e3, rankLoss:150, hpLoss:1500, weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Shoulder of Orion"] = new BlackOperation({ name:"Operation Shoulder of Orion", @@ -218,7 +218,7 @@ export const BlackOperations: IMap = {}; rankGain:2.5e3, rankLoss:500, hpLoss:1500, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isStealth:true + isStealth:true, }); BlackOperations["Operation Hyron"] = new BlackOperation({ name:"Operation Hyron", @@ -231,7 +231,7 @@ export const BlackOperations: IMap = {}; "means that the supercomputer may be able to reason abstractly " + "and become self-aware.

    " + "I do not need to remind you why sentient-level AIs pose a serious " + - "thread to all of mankind.

    " + + "threat to all of mankind.

    " + "The research for this project is being conducted at one of Fulcrum " + "Technologies secret facilities in Aevum, codenamed 'Alpha Ranch'. " + "Infiltrate the compound, delete and destroy the work, and then find and kill the " + @@ -240,7 +240,7 @@ export const BlackOperations: IMap = {}; rankGain:3e3, rankLoss:1e3, hpLoss:500, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Morpheus"] = new BlackOperation({ name:"Operation Morpheus", @@ -257,7 +257,7 @@ export const BlackOperations: IMap = {}; rankGain:4e3, rankLoss:1e3, hpLoss:100, weights:{hack:0.05,str:0.15,def:0.15,dex:0.3,agi:0.3,cha:0, int:0.05}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isStealth:true + isStealth:true, }); BlackOperations["Operation Ion Storm"] = new BlackOperation({ name:"Operation Ion Storm", @@ -272,7 +272,7 @@ export const BlackOperations: IMap = {}; rankGain:5e3, rankLoss:1e3, hpLoss:5000, weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Annihilus"] = new BlackOperation({ name:"Operation Annihilus", @@ -286,7 +286,7 @@ export const BlackOperations: IMap = {}; rankGain:7.5e3, rankLoss:1e3, hpLoss:10e3, weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Ultron"] = new BlackOperation({ name:"Operation Ultron", @@ -306,7 +306,7 @@ export const BlackOperations: IMap = {}; rankGain:10e3, rankLoss:2e3, hpLoss:10e3, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, - isKill:true + isKill:true, }); BlackOperations["Operation Centurion"] = new BlackOperation({ name:"Operation Centurion", @@ -342,4 +342,4 @@ export const BlackOperations: IMap = {}; weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, }); -})() \ No newline at end of file +})() diff --git a/src/Bladeburner/City.ts b/src/Bladeburner/City.ts index d159eab7e..75f8aff24 100644 --- a/src/Bladeburner/City.ts +++ b/src/Bladeburner/City.ts @@ -5,13 +5,13 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviv import { addOffset } from "../../utils/helpers/addOffset"; export class ChangePopulationByCountParams { - estChange: number = 0; - estOffset: number = 0; + estChange = 0; + estOffset = 0; } export class ChangePopulationByPercentageParams { - nonZero: boolean = false; - changeEstEqually: boolean = false; + nonZero = false; + changeEstEqually = false; } export class City { @@ -19,32 +19,32 @@ export class City { /** * Name of the city. */ - name: string = ""; + name = ""; /** * Population of the city. */ - pop: number = 0; + pop = 0; /** * Population estimation of the city. */ - popEst: number = 0; + popEst = 0; /** * Number of communities in the city. */ - comms: number = 0; + comms = 0; /** * Estimated number of communities in the city. */ - commsEst: number = 0; + commsEst = 0; /** * Chaos level of the city. */ - chaos: number = 0; + chaos = 0; constructor(name: string = BladeburnerConstants.CityNames[2]) { this.name = name; @@ -84,7 +84,7 @@ export class City { /** * p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%) */ - improvePopulationEstimateByPercentage(p: number, skillMult: number=1): void { + improvePopulationEstimateByPercentage(p: number, skillMult=1): void { p = p*skillMult; if (isNaN(p)) {throw new Error("NaN passed into City.improvePopulationEstimateByPercentage()");} if (this.popEst < this.pop) { @@ -97,7 +97,7 @@ export class City { } } - improveCommunityEstimate(n: number=1): void { + improveCommunityEstimate(n=1): void { if (isNaN(n)) {throw new Error("NaN passed into City.improveCommunityEstimate()");} if (this.commsEst < this.comms) { this.commsEst += n; @@ -154,19 +154,20 @@ export class City { if (this.chaos < 0) {this.chaos = 0;} } - /** - * Initiatizes a City object from a JSON save state. - */ - static fromJSON(value: any): City { - return Generic_fromJSON(City, value.data); - } - /** * Serialize the current object to a JSON save state. */ toJSON(): any { return Generic_toJSON("City", this); } + + /** + * Initiatizes a City object from a JSON save state. + */ + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): City { + return Generic_fromJSON(City, value.data); + } } Reviver.constructors.City = City; diff --git a/src/Bladeburner/Contract.ts b/src/Bladeburner/Contract.ts index 8b9662e66..332b98609 100644 --- a/src/Bladeburner/Contract.ts +++ b/src/Bladeburner/Contract.ts @@ -1,4 +1,4 @@ -// import { BladeburnerConstants } from "./data/Constants"; +import { IBladeburner } from "./IBladeburner"; import { Action, IActionParams } from "./Action"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; @@ -8,17 +8,18 @@ export class Contract extends Action { super(params); } - getActionTypeSkillSuccessBonus(inst: any): number { + getActionTypeSkillSuccessBonus(inst: IBladeburner): number { return inst.skillMultipliers.successChanceContract; } - static fromJSON(value: any): Contract { - return Generic_fromJSON(Contract, value.data); - } - toJSON(): any { return Generic_toJSON("Contract", this); } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Contract { + return Generic_fromJSON(Contract, value.data); + } } Reviver.constructors.Contract = Contract; \ No newline at end of file diff --git a/src/Bladeburner/GeneralActions.ts b/src/Bladeburner/GeneralActions.ts index 209b60002..ad457befa 100644 --- a/src/Bladeburner/GeneralActions.ts +++ b/src/Bladeburner/GeneralActions.ts @@ -11,7 +11,7 @@ export const GeneralActions: IMap = {}; name:actionName, desc:"Improve your abilities at the Bladeburner unit's specialized training " + "center. Doing this gives experience for all combat stats and also " + - "increases your max stamina." + "increases your max stamina.", }); actionName = "Field Analysis"; @@ -21,7 +21,7 @@ export const GeneralActions: IMap = {}; "Bladeburner's unit intelligence on Synthoid locations and " + "activities. Completing this action will improve the accuracy " + "of your Synthoid population estimated in the current city.

    " + - "Does NOT require stamina." + "Does NOT require stamina.", }); actionName = "Recruitment"; @@ -29,7 +29,7 @@ export const GeneralActions: IMap = {}; name:actionName, desc:"Attempt to recruit members for your Bladeburner team. These members " + "can help you conduct operations.

    " + - "Does NOT require stamina." + "Does NOT require stamina.", }); actionName = "Diplomacy"; @@ -37,7 +37,7 @@ export const GeneralActions: IMap = {}; name: actionName, desc: "Improve diplomatic relations with the Synthoid population. " + "Completing this action will reduce the Chaos level in your current city.

    " + - "Does NOT require stamina." + "Does NOT require stamina.", }); actionName = "Hyperbolic Regeneration Chamber"; diff --git a/src/Bladeburner/IAction.ts b/src/Bladeburner/IAction.ts new file mode 100644 index 000000000..2bae70182 --- /dev/null +++ b/src/Bladeburner/IAction.ts @@ -0,0 +1,71 @@ +import { IBladeburner } from "./IBladeburner"; + +export interface IStatsMultiplier { + [key: string]: number; + + hack: number; + str: number; + def: number; + dex: number; + agi: number; + cha: number; + int: number; +} + +export interface ISuccessChanceParams { + est: boolean; +} + +export interface IAction { + name: string; + desc: string; + + // Difficulty scales with level. See getDifficulty() method + level: number; + maxLevel: number; + autoLevel: boolean; + baseDifficulty: number; + difficultyFac: number; + + // Rank increase/decrease is affected by this exponent + rewardFac: number; + + successes: number; + failures: number; + + // All of these scale with level/difficulty + rankGain: number; + rankLoss: number; + hpLoss: number; + hpLost: number; + + // Action Category. Current categories are stealth and kill + isStealth: boolean; + isKill: boolean; + + /** + * Number of this contract remaining, and its growth rate + * Growth rate is an integer and the count will increase by that integer every "cycle" + */ + count: number; + countGrowth: number; + + // Weighting of each stat in determining action success rate + weights: IStatsMultiplier; + // Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1) + decays: IStatsMultiplier; + teamCount: number; + + getDifficulty(): number; + attempt(inst: IBladeburner): boolean; + getActionTimePenalty(): number; + getActionTime(inst: IBladeburner): number; + getTeamSuccessBonus(inst: IBladeburner): number; + getActionTypeSkillSuccessBonus(inst: IBladeburner): number; + getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number; + getChaosDifficultyBonus(inst: IBladeburner): number; + getSuccessChance(inst: IBladeburner, params: ISuccessChanceParams): number; + getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number; + setMaxLevel(baseSuccessesPerLevel: number): void; + toJSON(): any; +} \ No newline at end of file diff --git a/src/Bladeburner/IActionIdentifier.ts b/src/Bladeburner/IActionIdentifier.ts new file mode 100644 index 000000000..450ba774f --- /dev/null +++ b/src/Bladeburner/IActionIdentifier.ts @@ -0,0 +1,4 @@ +export interface IActionIdentifier { + name: string; + type: string; +} \ No newline at end of file diff --git a/src/Bladeburner/IBladeburner.ts b/src/Bladeburner/IBladeburner.ts new file mode 100644 index 000000000..7a7d9cd0e --- /dev/null +++ b/src/Bladeburner/IBladeburner.ts @@ -0,0 +1,39 @@ +import { IActionIdentifier } from "./IActionIdentifier"; +import { City } from "./City"; + +export interface IBladeburner { + numHosp: number; + moneyLost: number; + rank: number; + maxRank: number; + skillPoints: number; + totalSkillPoints: number; + teamSize: number; + teamLost: number; + storedCycles: number; + randomEventCounter: number; + actionTimeToComplete: number; + actionTimeCurrent: number; + action: IActionIdentifier; + cities: any; + city: string; + skills: any; + skillMultipliers: any; + staminaBonus: number; + maxStamina: number; + stamina: number; + contracts: any; + operations: any; + blackops: any; + logging: any; + automateEnabled: boolean; + automateActionHigh: number; + automateThreshHigh: number; + automateActionLow: number; + automateThreshLow: number; + consoleHistory: string[]; + consoleLogs: string[]; + + getCurrentCity(): City; + calculateStaminaPenalty(): number; +} \ No newline at end of file diff --git a/src/Bladeburner/Operation.ts b/src/Bladeburner/Operation.ts index 12718b493..9d9936ee4 100644 --- a/src/Bladeburner/Operation.ts +++ b/src/Bladeburner/Operation.ts @@ -1,3 +1,4 @@ +import { IBladeburner } from "./IBladeburner"; import { BladeburnerConstants } from "./data/Constants"; import { Action, IActionParams } from "./Action"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; @@ -8,8 +9,8 @@ export interface IOperationParams extends IActionParams { } export class Operation extends Action { - reqdRank: number = 100; - teamCount: number = 0; + reqdRank = 100; + teamCount = 0; constructor(params: IOperationParams | null = null) { super(params); @@ -18,38 +19,39 @@ export class Operation extends Action { } // For actions that have teams. To be implemented by subtypes. - getTeamSuccessBonus(inst: any): number { + getTeamSuccessBonus(inst: IBladeburner): number { if (this.teamCount && this.teamCount > 0) { this.teamCount = Math.min(this.teamCount, inst.teamSize); - let teamMultiplier = Math.pow(this.teamCount, 0.05); + const teamMultiplier = Math.pow(this.teamCount, 0.05); return teamMultiplier; } return 1; } - getActionTypeSkillSuccessBonus(inst: any): number { + getActionTypeSkillSuccessBonus(inst: IBladeburner): number { return inst.skillMultipliers.successChanceOperation; } - getChaosDifficultyBonus(inst: any, params: any): number { + getChaosDifficultyBonus(inst: IBladeburner/*, params: ISuccessChanceParams*/): number { const city = inst.getCurrentCity(); if (city.chaos > BladeburnerConstants.ChaosThreshold) { - let diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold); - let mult = Math.pow(diff, 0.1); + const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold); + const mult = Math.pow(diff, 0.1); return mult; } return 1; } - static fromJSON(value: any): Operation { - return Generic_fromJSON(Operation, value.data); - } - toJSON(): any { return Generic_toJSON("Operation", this); } + + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Operation { + return Generic_fromJSON(Operation, value.data); + } } Reviver.constructors.Operation = Operation; \ No newline at end of file diff --git a/src/Bladeburner/Skill.ts b/src/Bladeburner/Skill.ts index d901a25ca..deb84751e 100644 --- a/src/Bladeburner/Skill.ts +++ b/src/Bladeburner/Skill.ts @@ -33,36 +33,36 @@ export class Skill { name: string; desc: string; // Cost is in Skill Points - baseCost: number = 1; + baseCost = 1; // Additive cost increase per level - costInc: number = 1; - maxLvl: number = 0; + costInc = 1; + maxLvl = 0; /** * These benefits are additive. So total multiplier will be level (handled externally) times the * effects below */ - successChanceAll: number = 0; - successChanceStealth: number = 0; - successChanceKill: number = 0; - successChanceContract: number = 0; - successChanceOperation: number = 0; + successChanceAll = 0; + successChanceStealth = 0; + successChanceKill = 0; + successChanceContract = 0; + successChanceOperation = 0; /** * This multiplier affects everything that increases synthoid population/community estimate * e.g. Field analysis, Investigation Op, Undercover Op */ - successChanceEstimate: number = 0; - actionTime: number = 0; - effHack: number = 0; - effStr: number = 0; - effDef: number = 0; - effDex: number = 0; - effAgi: number = 0; - effCha: number = 0; - stamina: number = 0; - money: number = 0; - expGain: number = 0; + successChanceEstimate = 0; + actionTime = 0; + effHack = 0; + effStr = 0; + effDef = 0; + effDex = 0; + effAgi = 0; + effCha = 0; + stamina = 0; + money = 0; + expGain = 0; constructor(params: ISkillParams={name:"foo", desc:"foo"}) { if (!params.name) { diff --git a/src/Bladeburner/Skills.ts b/src/Bladeburner/Skills.ts index f762a296e..9fccf5614 100644 --- a/src/Bladeburner/Skills.ts +++ b/src/Bladeburner/Skills.ts @@ -10,55 +10,55 @@ export const Skills: IMap = {}; desc:"Each level of this skill increases your success chance " + "for all Contracts, Operations, and BlackOps by 3%", baseCost: 3, costInc: 2.1, - successChanceAll:3 + successChanceAll:3, }); Skills[SkillNames.Cloak] = new Skill({ name:SkillNames.Cloak, desc:"Each level of this skill increases your " + "success chance in stealth-related Contracts, Operations, and BlackOps by 5.5%", baseCost: 2, costInc: 1.1, - successChanceStealth:5.5 + successChanceStealth:5.5, }); Skills[SkillNames.ShortCircuit] = new Skill({ name:SkillNames.ShortCircuit, desc:"Each level of this skill increases your success chance " + "in Contracts, Operations, and BlackOps that involve retirement by 5.5%", baseCost: 2, costInc: 2.1, - successChanceKill:5.5 + successChanceKill:5.5, }); Skills[SkillNames.DigitalObserver] = new Skill({ name:SkillNames.DigitalObserver, desc:"Each level of this skill increases your success chance in " + "all Operations and BlackOps by 4%", baseCost: 2, costInc: 2.1, - successChanceOperation:4 + successChanceOperation:4, }); Skills[SkillNames.Tracer] = new Skill({ name:SkillNames.Tracer, desc:"Each level of this skill increases your success chance in " + "all Contracts by 4%", baseCost: 2, costInc: 2.1, - successChanceContract:4 + successChanceContract:4, }); Skills[SkillNames.Overclock] = new Skill({ name:SkillNames.Overclock, desc:"Each level of this skill decreases the time it takes " + "to attempt a Contract, Operation, and BlackOp by 1% (Max Level: 90)", baseCost: 3, costInc: 1.4, maxLvl: 90, - actionTime:1 + actionTime:1, }); Skills[SkillNames.Reaper] = new Skill({ name: SkillNames.Reaper, desc: "Each level of this skill increases your effective combat stats for Bladeburner actions by 2%", baseCost: 2, costInc: 2.1, - effStr: 2, effDef: 2, effDex: 2, effAgi: 2 + effStr: 2, effDef: 2, effDex: 2, effAgi: 2, }); Skills[SkillNames.EvasiveSystem] = new Skill({ name:SkillNames.EvasiveSystem, desc:"Each level of this skill increases your effective " + "dexterity and agility for Bladeburner actions by 4%", baseCost: 2, costInc: 2.1, - effDex: 4, effAgi: 4 + effDex: 4, effAgi: 4, }); Skills[SkillNames.Datamancer] = new Skill({ name:SkillNames.Datamancer, @@ -67,13 +67,13 @@ export const Skills: IMap = {}; "This affects all actions that can potentially increase " + "the accuracy of your synthoid population/community estimates.", baseCost:3, costInc:1, - successChanceEstimate:5 + successChanceEstimate:5, }); Skills[SkillNames.CybersEdge] = new Skill({ name:SkillNames.CybersEdge, desc:"Each level of this skill increases your max stamina by 2%", baseCost:1, costInc:3, - stamina:2 + stamina:2, }); Skills[SkillNames.HandsOfMidas] = new Skill({ name: SkillNames.HandsOfMidas, diff --git a/src/Bladeburner/data/Help.ts b/src/Bladeburner/data/Help.ts index ed87118b8..b08f86f10 100644 --- a/src/Bladeburner/data/Help.ts +++ b/src/Bladeburner/data/Help.ts @@ -1,4 +1,14 @@ -export const ConsoleHelpText: {} = { +export const ConsoleHelpText: { + helpList: string[]; + automate: string[]; + clear: string[]; + cls: string[]; + help: string[]; + log: string[]; + skill: string[]; + start: string[]; + stop: string[]; +} = { helpList: [ "Use 'help [command]' to get more information about a particular Bladeburner console command.", "", @@ -8,7 +18,7 @@ export const ConsoleHelpText: {} = { " log [en/dis] [type] Enable or disable logging for events and actions", " skill [action] [name] Level or display info about your Bladeburner skills", " start [type] [name] Start a Bladeburner action/task" , - " stop Stops your current Bladeburner action/task" + " stop Stops your current Bladeburner action/task", ], automate: [ "automate [var] [val] [hi/low]", @@ -30,17 +40,17 @@ export const ConsoleHelpText: {} = { "Using the four console commands above will set the automation to perform Tracking contracts " + "if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " + "50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " + - "exactly match whatever the name is in the UI." + "exactly match whatever the name is in the UI.", ], clear: [ "clear", "", - "Clears the console" + "Clears the console", ], cls: [ "cls", "", - "Clears the console" + "Clears the console", ], help: [ "help [command]", @@ -51,7 +61,7 @@ export const ConsoleHelpText: {} = { "", " help automate", "", - "will display specific information about using the automate console command" + "will display specific information about using the automate console command", ], log: [ "log [en/dis] [type]", @@ -71,7 +81,7 @@ export const ConsoleHelpText: {} = { "Logging can be universally enabled/disabled using the 'all' keyword:", "", " log dis all", - " log en all" + " log en all", ], skill: [ "skill [action] [name]", @@ -91,7 +101,7 @@ export const ConsoleHelpText: {} = { "", "This console command can also be used to level up skills:", "", - " skill level [skill name]" + " skill level [skill name]", ], start: [ "start [type] [name]", @@ -106,11 +116,11 @@ export const ConsoleHelpText: {} = { "Examples:", "", " start contract Tracking", - " start op 'Undercover Operation'" + " start op 'Undercover Operation'", ], stop:[ "stop", "", - "Stop your current action and go idle." + "Stop your current action and go idle.", ], } \ No newline at end of file diff --git a/src/Bladeburner/ui/BlackOperationsPage.tsx b/src/Bladeburner/ui/BlackOperationsPage.tsx index 134147551..7f73397c1 100644 --- a/src/Bladeburner/ui/BlackOperationsPage.tsx +++ b/src/Bladeburner/ui/BlackOperationsPage.tsx @@ -38,7 +38,7 @@ for (var i = blackops.length-1; i >= 0 ; --i) { import * as React from "react"; -export function BlackOperationsPage(inst: any): React.ReactElement { +export function BlackOperationsPage(): React.ReactElement { // Put Black Operations in sequence of required rank const blackops = []; for (const name in BlackOperations) { @@ -55,9 +55,8 @@ export function BlackOperationsPage(inst: any): React.ReactElement { Black Operations (Black Ops) are special, one-time covert operations. Each Black Op must be unlocked successively by completing the one before it.

    Your ultimate goal to climb through the ranks of Bladeburners is to complete all of the Black Ops.

    Like normal operations, you may use a team for Black Ops. Failing a black op will incur heavy HP and rank losses.

    - {blackops.map( op => -
    -
    + {blackops.map(() =>
    +
    , )}
    ) } diff --git a/src/Casino/CoinFlip.tsx b/src/Casino/CoinFlip.tsx index a9c10948d..e67935073 100644 --- a/src/Casino/CoinFlip.tsx +++ b/src/Casino/CoinFlip.tsx @@ -41,7 +41,7 @@ export class CoinFlip extends Game { this.updateInvestment = this.updateInvestment.bind(this); } - updateInvestment(e: React.FormEvent) { + updateInvestment(e: React.FormEvent): void { let investment: number = parseInt(e.currentTarget.value); if (isNaN(investment)) { investment = minPlay; @@ -55,7 +55,7 @@ export class CoinFlip extends Game { this.setState({investment: investment}); } - play(guess: string) { + play(guess: string): void { if(this.reachedLimit(this.props.p)) return; const v = BadRNG.random(); let letter: string; @@ -80,7 +80,7 @@ export class CoinFlip extends Game { } - render() { + render(): React.ReactNode { return <>
     +———————+
    @@ -89,7 +89,7 @@ export class CoinFlip extends Game { | | | |
    +———————+
    - Play for:
    + Play for:
    this.play('H'))} text={"Head!"} disabled={this.state.playLock} /> this.play('T'))} text={"Tail!"} disabled={this.state.playLock} />

    {this.state.status}

    diff --git a/src/Casino/RNG.ts b/src/Casino/RNG.ts index 483bdf3b7..00550020f 100644 --- a/src/Casino/RNG.ts +++ b/src/Casino/RNG.ts @@ -1,6 +1,6 @@ export interface RNG { - random(): number + random(): number; } /* @@ -9,16 +9,16 @@ export interface RNG { */ class RNG0 implements RNG { x: number; - m: number = 1024; - a: number = 341; - c: number = 1; + m = 1024; + a = 341; + c = 1; constructor() { this.x = 0; this.reset(); } - step() { + step(): void { this.x = (this.a*this.x+this.c) % this.m; } @@ -27,7 +27,7 @@ class RNG0 implements RNG { return this.x/this.m; } - reset() { + reset(): void { this.x = (new Date()).getTime() % this.m; } } @@ -39,9 +39,9 @@ export const BadRNG: RNG0 = new RNG0(); * The period is 6e12. */ export class WHRNG implements RNG { - s1: number = 0; - s2: number = 0; - s3: number = 0; + s1 = 0; + s2 = 0; + s3 = 0; constructor(totalPlaytime: number) { // This one is seeded by the players total play time. @@ -51,7 +51,7 @@ export class WHRNG implements RNG { this.s3 = v; } - step() { + step(): void { this.s1 = (171 * this.s1) % 30269; this.s2 = (172 * this.s2) % 30307; this.s3 = (170 * this.s3) % 30323; diff --git a/src/Casino/Roulette.tsx b/src/Casino/Roulette.tsx index 158dfb528..fcfda71c2 100644 --- a/src/Casino/Roulette.tsx +++ b/src/Casino/Roulette.tsx @@ -28,10 +28,6 @@ function isRed(n: number): boolean { 21, 23, 25, 27, 30, 32, 34, 36].includes(n); } -function isBlack(n: number): boolean { - return !isRed(n); -} - type Strategy = { match: (n: number) => boolean; payout: number; @@ -102,14 +98,14 @@ const strategies: { Third2: { match: (n: number): boolean => { if (n === 0) return false; - return 13 <= n && n <= 24; + return n >= 13 && n <= 24; }, payout: 2, }, Third3: { match: (n: number): boolean => { if (n === 0) return false; - return 25 <= n; + return n >= 25; }, payout: 2, }, @@ -125,7 +121,7 @@ function Single(s: number): Strategy { } export class Roulette extends Game { - interval: number = -1; + interval = -1; rng: WHRNG; constructor(props: IProps) { @@ -140,7 +136,7 @@ export class Roulette extends Game { lock: true, strategy: { payout: 0, - match: (n: number): boolean => { return false }, + match: (): boolean => { return false }, }, } @@ -150,21 +146,21 @@ export class Roulette extends Game { } - componentDidMount() { + componentDidMount(): void { this.interval = setInterval(this.step, 50); } - step() { + step(): void { if (!this.state.lock) { this.setState({n: Math.floor(Math.random()*37)}); } } - componentWillUnmount() { + componentWillUnmount(): void { clearInterval(this.interval); } - updateInvestment(e: React.FormEvent) { + updateInvestment(e: React.FormEvent): void { let investment: number = parseInt(e.currentTarget.value); if (isNaN(investment)) { investment = minPlay; @@ -178,13 +174,13 @@ export class Roulette extends Game { this.setState({investment: investment}); } - currentNumber() { + currentNumber(): string { if (this.state.n === 0) return '0'; const color = isRed(this.state.n) ? 'R' : 'B'; return `${this.state.n}${color}`; } - play(s: Strategy) { + play(s: Strategy): void { if(this.reachedLimit(this.props.p)) return; this.setState({ canPlay: false, @@ -223,10 +219,10 @@ export class Roulette extends Game { } - render() { + render(): React.ReactNode { return <>

    {this.currentNumber()}

    - +

    {this.state.status}

    diff --git a/src/Casino/SlotMachine.tsx b/src/Casino/SlotMachine.tsx index 470ef5301..7b61934a8 100644 --- a/src/Casino/SlotMachine.tsx +++ b/src/Casino/SlotMachine.tsx @@ -20,7 +20,7 @@ type IState = { } // statically shuffled array of symbols. -let symbols = ["D", "C", "$", "?", "♥", "A", "C", "B", "C", "E", "B", "E", "C", +const symbols = ["D", "C", "$", "?", "♥", "A", "C", "B", "C", "E", "B", "E", "C", "*", "D", "♥", "B", "A", "A", "A", "C", "A", "D", "B", "E", "?", "D", "*", "@", "♥", "B", "E", "?"]; @@ -63,7 +63,7 @@ const maxPlay = 1e6; export class SlotMachine extends Game { rng: WHRNG; - interval: number = -1; + interval = -1; constructor(props: IProps) { super(props); @@ -86,11 +86,11 @@ export class SlotMachine extends Game { this.updateInvestment = this.updateInvestment.bind(this); } - componentDidMount() { + componentDidMount(): void { this.interval = setInterval(this.step, 50); } - step() { + step(): void { let stoppedOne = false; const index = this.state.index.slice(); for(const i in index) { @@ -106,7 +106,7 @@ export class SlotMachine extends Game { } } - componentWillUnmount() { + componentWillUnmount(): void { clearInterval(this.interval); } @@ -118,7 +118,7 @@ export class SlotMachine extends Game { ]; } - play() { + play(): void { if(this.reachedLimit(this.props.p)) return; this.setState({status: 'playing'}); this.win(this.props.p, -this.state.investment); @@ -127,7 +127,7 @@ export class SlotMachine extends Game { setTimeout(this.lock, this.rng.random()*2000+1000); } - lock() { + lock(): void { this.setState({ locks: [ Math.floor(this.rng.random()*symbols.length), @@ -139,10 +139,10 @@ export class SlotMachine extends Game { }) } - checkWinnings() { + checkWinnings(): void { const t = this.getTable(); const getPaylineData = function(payline: number[][]): string[] { - let data = []; + const data = []; for(const point of payline) { data.push(t[point[0]][point[1]]); } @@ -176,14 +176,14 @@ export class SlotMachine extends Game { if(this.reachedLimit(this.props.p)) return; } - unlock() { + unlock(): void { this.setState({ locks: [-1, -1, -1, -1, -1], canPlay: false, }) } - updateInvestment(e: React.FormEvent) { + updateInvestment(e: React.FormEvent): void { let investment: number = parseInt(e.currentTarget.value); if (isNaN(investment)) { investment = minPlay; @@ -197,7 +197,7 @@ export class SlotMachine extends Game { this.setState({investment: investment}); } - render() { + render(): React.ReactNode { const t = this.getTable(); return <>
    @@ -209,7 +209,7 @@ export class SlotMachine extends Game {
     | | {symbols[(this.state.index[0]+1)%symbols.length]} | {symbols[(this.state.index[1]+1)%symbols.length]} | {symbols[(this.state.index[2]+1)%symbols.length]} | {symbols[(this.state.index[3]+1)%symbols.length]} | {symbols[(this.state.index[4]+1)%symbols.length]} | |
    +———————————————————————+
    - +

    {this.state.status}

    Pay lines

    diff --git a/src/CinematicText.js b/src/CinematicText.js index f1899a5b9..7cdb67ff4 100644 --- a/src/CinematicText.js +++ b/src/CinematicText.js @@ -90,7 +90,7 @@ function cinematicTextEnd() { var mainMenu = document.getElementById("mainmenu-container"); container.appendChild(createElement("br")); - return new Promise (function(resolve, reject) { + return new Promise (function(resolve) { container.appendChild(createElement("a", { class:"a-link-button", innerText:"Continue...", clickListener:()=>{ @@ -99,7 +99,7 @@ function cinematicTextEnd() { mainMenu.style.visibility = "visible"; cinematicTextFlag = false; resolve(); - } + }, })); }); } diff --git a/src/CodingContractGenerator.ts b/src/CodingContractGenerator.ts index 6b5e62ad4..49f89c4ee 100644 --- a/src/CodingContractGenerator.ts +++ b/src/CodingContractGenerator.ts @@ -2,7 +2,7 @@ import { CodingContract, CodingContractRewardType, CodingContractTypes, - ICodingContractReward + ICodingContractReward, } from "./CodingContracts"; import { Factions } from "./Faction/Factions"; import { Player } from "./Player"; @@ -15,7 +15,7 @@ import { HacknetServer } from "./Hacknet/HacknetServer"; import { getRandomInt } from "../utils/helpers/getRandomInt"; -export function generateRandomContract() { +export function generateRandomContract(): void { // First select a random problem type const problemType = getRandomProblemType(); @@ -31,7 +31,7 @@ export function generateRandomContract() { randServer.addContract(contract); } -export function generateRandomContractOnHome() { +export function generateRandomContractOnHome(): void { // First select a random problem type const problemType = getRandomProblemType(); @@ -53,7 +53,7 @@ export interface IGenerateContractParams { fn?: string; } -export function generateContract(params: IGenerateContractParams) { +export function generateContract(params: IGenerateContractParams): void { // Problem Type let problemType; const problemTypes = Object.keys(CodingContractTypes); @@ -88,7 +88,7 @@ export function generateContract(params: IGenerateContractParams) { fn = getRandomFilename(server, reward); } - let contract = new CodingContract(fn, problemType, reward); + const contract = new CodingContract(fn, problemType, reward); server.addContract(contract); } @@ -117,15 +117,15 @@ function sanitizeRewardType(rewardType: CodingContractRewardType): CodingContrac return type; } -function getRandomProblemType() { +function getRandomProblemType(): string { const problemTypes = Object.keys(CodingContractTypes); - let randIndex = getRandomInt(0, problemTypes.length - 1); + const randIndex = getRandomInt(0, problemTypes.length - 1); return problemTypes[randIndex]; } function getRandomReward(): ICodingContractReward { - let reward: ICodingContractReward = { + const reward: ICodingContractReward = { name: "", type: getRandomInt(0, CodingContractRewardType.Money), }; @@ -145,8 +145,8 @@ function getRandomReward(): ICodingContractReward { case CodingContractRewardType.FactionReputation: { // Get a random faction that player is a part of. That // faction must allow hacking contracts - var numFactions = factionsThatAllowHacking.length; - var randFaction = factionsThatAllowHacking[getRandomInt(0, numFactions - 1)]; + const numFactions = factionsThatAllowHacking.length; + const randFaction = factionsThatAllowHacking[getRandomInt(0, numFactions - 1)]; reward.name = randFaction; break; } diff --git a/src/CodingContracts.ts b/src/CodingContracts.ts index 1af8fb5fa..3b93250b8 100644 --- a/src/CodingContracts.ts +++ b/src/CodingContracts.ts @@ -2,7 +2,7 @@ import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, - SolverFunc + SolverFunc, } from "./data/codingcontracttypes"; import { IMap } from "./types"; @@ -10,7 +10,7 @@ import { IMap } from "./types"; import { Generic_fromJSON, Generic_toJSON, - Reviver + Reviver, } from "../utils/JSONReviver"; import { KEY } from "../utils/helpers/keyCodes"; import { createElement } from "../utils/uiHelpers/createElement"; @@ -108,12 +108,6 @@ export interface ICodingContractReward { * The player receives a reward if the problem is solved correctly */ export class CodingContract { - /** - * Initiatizes a CodingContract from a JSON save state. - */ - static fromJSON(value: any): CodingContract { - return Generic_fromJSON(CodingContract, value.data); - } /* Relevant data for the contract's problem */ data: any; @@ -126,13 +120,13 @@ export class CodingContract { reward: ICodingContractReward | null; /* Number of times the Contract has been attempted */ - tries: number = 0; + tries = 0; /* String representing the contract's type. Must match type in ContractTypes */ type: string; - constructor(fn: string = "", - type: string = "Find Largest Prime Factor", + constructor(fn = "", + type = "Find Largest Prime Factor", reward: ICodingContractReward | null = null) { this.fn = fn; if (!this.fn.endsWith(".cct")) { @@ -178,9 +172,9 @@ export class CodingContract { */ async prompt(): Promise { // tslint:disable-next-line - return new Promise((resolve: Function, reject: Function) => { + return new Promise((resolve) => { const contractType: CodingContractType = CodingContractTypes[this.type]; - const popupId: string = `coding-contract-prompt-popup-${this.fn}`; + const popupId = `coding-contract-prompt-popup-${this.fn}`; const title: HTMLElement = createElement("h1", { innerHTML: this.type, }); @@ -190,10 +184,16 @@ export class CodingContract { "after which the contract will self-destruct.

    ", `${contractType.desc(this.data).replace(/\n/g, "
    ")}`].join(" "), }); - let answerInput: HTMLInputElement; let solveBtn: HTMLElement; - let cancelBtn: HTMLElement; - answerInput = createElement("input", { + const cancelBtn = createElement("a", { + class: "a-link-button", + clickListener: () => { + resolve(CodingContractResult.Cancelled); + removeElementById(popupId); + }, + innerText: "Cancel", + }); + const answerInput = createElement("input", { onkeydown: (e: any) => { if (e.keyCode === KEY.ENTER && answerInput.value !== "") { e.preventDefault(); @@ -219,14 +219,6 @@ export class CodingContract { }, innerText: "Solve", }); - cancelBtn = createElement("a", { - class: "a-link-button", - clickListener: () => { - resolve(CodingContractResult.Cancelled); - removeElementById(popupId); - }, - innerText: "Cancel", - }); const lineBreak: HTMLElement = createElement("br"); createPopup(popupId, [title, lineBreak, txt, lineBreak, lineBreak, answerInput, solveBtn, cancelBtn]); answerInput.focus(); @@ -239,6 +231,14 @@ export class CodingContract { toJSON(): any { return Generic_toJSON("CodingContract", this); } + + /** + * Initiatizes a CodingContract from a JSON save state. + */ + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): CodingContract { + return Generic_fromJSON(CodingContract, value.data); + } } Reviver.constructors.CodingContract = CodingContract; diff --git a/src/Company/Companies.ts b/src/Company/Companies.ts index 60b78c295..6c775b42c 100644 --- a/src/Company/Companies.ts +++ b/src/Company/Companies.ts @@ -6,7 +6,7 @@ import { Reviver } from "../../utils/JSONReviver"; export let Companies: IMap = {}; -function addCompany(params: IConstructorParams) { +function addCompany(params: IConstructorParams): void { if (Companies[params.name] != null) { console.warn(`Duplicate Company Position being defined: ${params.name}`); } @@ -15,7 +15,7 @@ function addCompany(params: IConstructorParams) { // Used to initialize new Company objects for the Companies map // Called when creating new game or after a prestige/reset -export function initCompanies() { +export function initCompanies(): void { // Save Old Company data for 'favor' const oldCompanies = Companies; @@ -40,11 +40,11 @@ export function initCompanies() { } // Used to load Companies map from a save -export function loadCompanies(saveString: string) { +export function loadCompanies(saveString: string): void { Companies = JSON.parse(saveString, Reviver); } // Utility function to check if a string is valid company name -export function companyExists(name: string) { +export function companyExists(name: string): boolean { return Companies.hasOwnProperty(name); } diff --git a/src/Company/Company.ts b/src/Company/Company.ts index 52dc44cd1..6bf877a94 100644 --- a/src/Company/Company.ts +++ b/src/Company/Company.ts @@ -25,12 +25,6 @@ const DefaultConstructorParams: IConstructorParams = { } export class Company { - /** - * Initiatizes a Company from a JSON save state. - */ - static fromJSON(value: any): Company { - return Generic_fromJSON(Company, value.data); - } /** * Company name @@ -136,7 +130,7 @@ export class Company { gainFavor(): void { if (this.favor == null) { this.favor = 0; } if (this.rolloverRep == null) { this.rolloverRep = 0; } - var res = this.getFavorGain(); + const res = this.getFavorGain(); if (res.length != 2) { console.error("Invalid result from getFavorGain() function"); return; @@ -170,6 +164,14 @@ export class Company { toJSON(): any { return Generic_toJSON("Company", this); } + + /** + * Initiatizes a Company from a JSON save state. + */ + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Company { + return Generic_fromJSON(Company, value.data); + } } Reviver.constructors.Company = Company; diff --git a/src/Company/CompanyPositions.ts b/src/Company/CompanyPositions.ts index 27578f0d6..097abe2ba 100644 --- a/src/Company/CompanyPositions.ts +++ b/src/Company/CompanyPositions.ts @@ -5,7 +5,7 @@ import { IMap } from "../types"; export const CompanyPositions: IMap = {}; -function addCompanyPosition(params: IConstructorParams) { +function addCompanyPosition(params: IConstructorParams): void { if (CompanyPositions[params.name] != null) { console.warn(`Duplicate Company Position being defined: ${params.name}`); } diff --git a/src/Company/GetJobRequirementText.ts b/src/Company/GetJobRequirementText.ts index b3d023aa9..c9da1b541 100644 --- a/src/Company/GetJobRequirementText.ts +++ b/src/Company/GetJobRequirementText.ts @@ -5,8 +5,8 @@ import { CompanyPosition } from "./CompanyPosition"; * Returns a string with the given CompanyPosition's stat requirements */ -export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext: boolean = false): string { - let reqText: string = ""; +export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext = false): string { + let reqText = ""; const offset: number = company.jobStatReqOffset; const reqHacking: number = pos.requiredHacking > 0 ? pos.requiredHacking+offset : 0; const reqStrength: number = pos.requiredStrength > 0 ? pos.requiredStrength+offset : 0; diff --git a/src/Company/data/CompaniesMetadata.ts b/src/Company/data/CompaniesMetadata.ts index 06f5dc872..a4d833fec 100644 --- a/src/Company/data/CompaniesMetadata.ts +++ b/src/Company/data/CompaniesMetadata.ts @@ -95,7 +95,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 3, salaryMultiplier: 3, @@ -107,7 +107,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 3, salaryMultiplier: 3, @@ -119,7 +119,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 2.6, salaryMultiplier: 2.6, @@ -131,7 +131,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 2.75, salaryMultiplier: 2.75, @@ -143,7 +143,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 2.75, salaryMultiplier: 2.75, @@ -155,7 +155,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 2.25, salaryMultiplier: 2.25, @@ -167,7 +167,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 2.25, salaryMultiplier: 2.25, @@ -179,7 +179,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 2.5, salaryMultiplier: 2.5, @@ -191,7 +191,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 2.2, salaryMultiplier: 2.2, @@ -202,7 +202,7 @@ export const companiesMetadata: IConstructorParams[] = [ info: "", companyPositions: Object.assign({}, AllTechnologyPositions, - AllBusinessPositions + AllBusinessPositions, ), expMultiplier: 2, salaryMultiplier: 2, @@ -214,7 +214,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllSoftwareConsultantPositions, - AllBusinessPositions + AllBusinessPositions, ), expMultiplier: 1.8, salaryMultiplier: 1.8, @@ -226,7 +226,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, CEOOnly, AllTechnologyPositions, - AllSoftwareConsultantPositions + AllSoftwareConsultantPositions, ), expMultiplier: 1.75, salaryMultiplier: 1.75, @@ -238,7 +238,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, CEOOnly, AllTechnologyPositions, - AllSoftwareConsultantPositions + AllSoftwareConsultantPositions, ), expMultiplier: 1.8, salaryMultiplier: 1.8, @@ -250,7 +250,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSoftwareConsultantPositions + AllSoftwareConsultantPositions, ), expMultiplier: 1.8, salaryMultiplier: 1.8, @@ -262,7 +262,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSoftwareConsultantPositions + AllSoftwareConsultantPositions, ), expMultiplier: 1.9, salaryMultiplier: 1.9, @@ -274,7 +274,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSoftwareConsultantPositions + AllSoftwareConsultantPositions, ), expMultiplier: 2, salaryMultiplier: 2, @@ -286,7 +286,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllTechnologyPositions, AllBusinessPositions, - AllSoftwareConsultantPositions + AllSoftwareConsultantPositions, ), expMultiplier: 1.9, salaryMultiplier: 1.9, @@ -299,7 +299,7 @@ export const companiesMetadata: IConstructorParams[] = [ CEOOnly, OperationsManagerOnly, AllTechnologyPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 1.7, salaryMultiplier: 1.7, @@ -351,7 +351,7 @@ export const companiesMetadata: IConstructorParams[] = [ AllTechnologyPositions, AllBusinessPositions, AllSoftwareConsultantPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 1.8, salaryMultiplier: 1.8, @@ -364,7 +364,7 @@ export const companiesMetadata: IConstructorParams[] = [ AllTechnologyPositions, AllBusinessPositions, AllSoftwareConsultantPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 1.75, salaryMultiplier: 1.75, @@ -379,7 +379,7 @@ export const companiesMetadata: IConstructorParams[] = [ SecurityEngineerPositions, AllITPositions, AllSecurityPositions, - AllAgentPositions + AllAgentPositions, ), expMultiplier: 2, salaryMultiplier: 2, @@ -394,7 +394,7 @@ export const companiesMetadata: IConstructorParams[] = [ SecurityEngineerPositions, AllITPositions, AllSecurityPositions, - AllAgentPositions + AllAgentPositions, ), expMultiplier: 2, salaryMultiplier: 2, @@ -409,7 +409,7 @@ export const companiesMetadata: IConstructorParams[] = [ AllITPositions, AllSecurityPositions, AllAgentPositions, - AllSoftwareConsultantPositions + AllSoftwareConsultantPositions, ), expMultiplier: 1.5, salaryMultiplier: 1.5, @@ -422,7 +422,7 @@ export const companiesMetadata: IConstructorParams[] = [ AllTechnologyPositions, AllSoftwareConsultantPositions, AllBusinessPositions, - AllSecurityPositions + AllSecurityPositions, ), expMultiplier: 1.4, salaryMultiplier: 1.4, @@ -433,7 +433,7 @@ export const companiesMetadata: IConstructorParams[] = [ info: "", companyPositions: Object.assign({}, SoftwarePositionsUpToLeadDeveloper, - BusinessPositionsUpToOperationsManager + BusinessPositionsUpToOperationsManager, ), expMultiplier: 1.3, salaryMultiplier: 1.3, @@ -445,7 +445,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, SoftwarePositionsUpToLeadDeveloper, BusinessPositionsUpToOperationsManager, - AllSoftwareConsultantPositions + AllSoftwareConsultantPositions, ), expMultiplier: 1.5, salaryMultiplier: 1.5, @@ -456,7 +456,7 @@ export const companiesMetadata: IConstructorParams[] = [ info: "", companyPositions: Object.assign({}, AllSecurityPositions, - SoftwarePositionsUpToLeadDeveloper + SoftwarePositionsUpToLeadDeveloper, ), expMultiplier: 1.3, salaryMultiplier: 1.3, @@ -466,7 +466,7 @@ export const companiesMetadata: IConstructorParams[] = [ name: LocationName.VolhavenSysCoreSecurities, info: "", companyPositions: Object.assign({}, - AllTechnologyPositions + AllTechnologyPositions, ), expMultiplier: 1.3, salaryMultiplier: 1.3, @@ -476,7 +476,7 @@ export const companiesMetadata: IConstructorParams[] = [ name: LocationName.VolhavenCompuTek, info: "", companyPositions: Object.assign({}, - AllTechnologyPositions + AllTechnologyPositions, ), expMultiplier: 1.2, salaryMultiplier: 1.2, @@ -486,7 +486,7 @@ export const companiesMetadata: IConstructorParams[] = [ name: LocationName.AevumNetLinkTechnologies, info: "", companyPositions: Object.assign({}, - AllTechnologyPositions + AllTechnologyPositions, ), expMultiplier: 1.2, salaryMultiplier: 1.2, @@ -509,7 +509,7 @@ export const companiesMetadata: IConstructorParams[] = [ name: LocationName.Sector12FoodNStuff, info: "", companyPositions: Object.assign({}, - EmployeeOnly, PartTimeEmployeeOnly + EmployeeOnly, PartTimeEmployeeOnly, ), expMultiplier: 1, salaryMultiplier: 1, @@ -519,7 +519,7 @@ export const companiesMetadata: IConstructorParams[] = [ name: LocationName.Sector12JoesGuns, info: "", companyPositions: Object.assign({}, - EmployeeOnly, PartTimeEmployeeOnly + EmployeeOnly, PartTimeEmployeeOnly, ), expMultiplier: 1, salaryMultiplier: 1, @@ -531,7 +531,7 @@ export const companiesMetadata: IConstructorParams[] = [ companyPositions: Object.assign({}, AllSoftwarePositions, AllSoftwareConsultantPositions, - AllITPositions + AllITPositions, ), expMultiplier: 1.1, salaryMultiplier: 1.1, @@ -541,7 +541,7 @@ export const companiesMetadata: IConstructorParams[] = [ name: LocationName.NewTokyoNoodleBar, info: "", companyPositions: Object.assign({}, - WaiterOnly, PartTimeWaiterOnly + WaiterOnly, PartTimeWaiterOnly, ), expMultiplier: 1, salaryMultiplier: 1, diff --git a/src/Company/data/companypositionnames.ts b/src/Company/data/companypositionnames.ts index 857e1cfaf..c1d4a46b3 100644 --- a/src/Company/data/companypositionnames.ts +++ b/src/Company/data/companypositionnames.ts @@ -8,23 +8,23 @@ export const SoftwareCompanyPositions: string[] = [ "Head of Software", "Head of Engineering", "Vice President of Technology", - "Chief Technology Officer" + "Chief Technology Officer", ]; export const ITCompanyPositions: string[] = [ "IT Intern", "IT Analyst", "IT Manager", - "Systems Administrator" + "Systems Administrator", ]; export const SecurityEngineerCompanyPositions: string[] = [ - "Security Engineer" + "Security Engineer", ]; export const NetworkEngineerCompanyPositions: string[] = [ "Network Engineer", - "Network Administrator" + "Network Administrator", ]; export const BusinessCompanyPositions: string[] = [ @@ -33,7 +33,7 @@ export const BusinessCompanyPositions: string[] = [ "Business Manager", "Operations Manager", "Chief Financial Officer", - "Chief Executive Officer" + "Chief Executive Officer", ]; export const SecurityCompanyPositions: string[] = [ @@ -42,31 +42,31 @@ export const SecurityCompanyPositions: string[] = [ "Security Guard", "Security Officer", "Security Supervisor", - "Head of Security" + "Head of Security", ]; export const AgentCompanyPositions: string[] = [ "Field Agent", "Secret Agent", - "Special Operative" + "Special Operative", ]; export const MiscCompanyPositions: string[] = [ "Waiter", - "Employee" + "Employee", ]; export const SoftwareConsultantCompanyPositions: string[] = [ "Software Consultant", - "Senior Software Consultant" + "Senior Software Consultant", ]; export const BusinessConsultantCompanyPositions: string[] = [ "Business Consultant", - "Senior Business Consultant" + "Senior Business Consultant", ]; export const PartTimeCompanyPositions: string[] = [ "Part-time Waiter", - "Part-time Employee" + "Part-time Employee", ]; diff --git a/src/Constants.ts b/src/Constants.ts index 14e846d84..de47de68c 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -5,7 +5,7 @@ */ import { IMap } from "./types"; -export let CONSTANTS: IMap = { +export const CONSTANTS: IMap = { Version: "0.51.6", /** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience @@ -268,5 +268,5 @@ export let CONSTANTS: IMap = { * so many documentation and typos fixes (@Pimgd) * A corruption visual effect has been added to location with servers that have backdoor installed. (@dewint) - ` + `, } \ No newline at end of file diff --git a/src/Corporation/Corporation.jsx b/src/Corporation/Corporation.jsx index 08403439a..4d9809401 100644 --- a/src/Corporation/Corporation.jsx +++ b/src/Corporation/Corporation.jsx @@ -5,7 +5,6 @@ import { CorporationUpgrades } from "./data/Corporation import { EmployeePositions } from "./EmployeePositions"; import { Industries, IndustryStartingCosts, - IndustryDescriptions, IndustryResearchTrees } from "./IndustryData"; import { IndustryUpgrades } from "./IndustryUpgrades"; import { Material } from "./Material"; @@ -15,11 +14,8 @@ import { ResearchMap } from "./ResearchMap"; import { Warehouse } from "./Warehouse"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; -import { CONSTANTS } from "../Constants"; -import { Factions } from "../Faction/Factions"; import { showLiterature } from "../Literature/LiteratureHelpers"; import { LiteratureNames } from "../Literature/data/LiteratureNames"; -import { createCityMap } from "../Locations/Cities"; import { CityName } from "../Locations/data/CityNames"; import { Player } from "../Player"; @@ -29,7 +25,6 @@ import { Page, routing } from "../ui/navigationTr import { calculateEffectWithFactors } from "../utils/calculateEffectWithFactors"; import { dialogBoxCreate } from "../../utils/DialogBox"; -import { clearSelector } from "../../utils/uiHelpers/clearSelector"; import { Reviver, Generic_toJSON, Generic_fromJSON } from "../../utils/JSONReviver"; @@ -99,7 +94,6 @@ export const BaseMaxProducts = 3; // Initial value for maximum let researchTreeBoxOpened = false; let researchTreeBox = null; $(document).mousedown(function(event) { - const boxId = "corporation-research-popup-box"; const contentId = "corporation-research-popup-box-content"; if (researchTreeBoxOpened) { if ( $(event.target).closest("#" + contentId).get(0) == null ) { @@ -111,7 +105,6 @@ $(document).mousedown(function(event) { } }); -var empManualAssignmentModeActive = false; function Industry(params={}) { this.offices = { //Maps locations to offices. 0 if no office at that location [CityName.Aevum]: 0, @@ -122,7 +115,7 @@ function Industry(params={}) { }), [CityName.NewTokyo]: 0, [CityName.Ishima]: 0, - [CityName.Volhaven]: 0 + [CityName.Volhaven]: 0, }; this.name = params.name ? params.name : 0; @@ -183,7 +176,7 @@ function Industry(params={}) { }), [CityName.NewTokyo]: 0, [CityName.Ishima]: 0, - [CityName.Volhaven]: 0 + [CityName.Volhaven]: 0, }; this.init(); @@ -378,7 +371,7 @@ Industry.prototype.init = function() { "Metal": 5, "Energy": 5, "Water": 2, - "Hardware": 4 + "Hardware": 4, } this.prodMats = ["RealEstate"]; this.makesProducts = true; @@ -441,8 +434,7 @@ Industry.prototype.calculateProductionFactors = function() { continue; } - var materials = warehouse.materials, - office = this.offices[city]; + var materials = warehouse.materials; var cityMult = Math.pow(0.002 * materials.RealEstate.qty+1, this.reFac) * Math.pow(0.002 * materials.Hardware.qty+1, this.hwFac) * @@ -535,7 +527,7 @@ Industry.prototype.process = function(marketCycles=1, state, company) { } // Process change in demand and competition for this industry's materials -Industry.prototype.processMaterialMarket = function(marketCycles=1) { +Industry.prototype.processMaterialMarket = function() { //References to prodMats and reqMats var reqMats = this.reqMats, prodMats = this.prodMats; @@ -589,7 +581,7 @@ Industry.prototype.processProductMarket = function(marketCycles=1) { //Process production, purchase, and import/export of materials Industry.prototype.processMaterials = function(marketCycles=1, company) { - var revenue = 0, expenses = 0, industry = this; + var revenue = 0, expenses = 0; this.calculateProductionFactors(); //At the start of the export state, set the imports of everything to 0 @@ -642,7 +634,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) { mat.qty += buyAmt; expenses += (buyAmt * mat.bCost); } - })(matName, industry); + })(matName, this); this.updateWarehouseSizeUsed(warehouse); } } //End process purchase of materials @@ -1003,7 +995,7 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio if (warehouse instanceof Warehouse) { switch(this.state) { - case "PRODUCTION": + case "PRODUCTION": { //Calculate the maximum production of this material based //on the office's productivity var maxProd = this.getOfficeProductivity(office, {forProduct:true}) @@ -1065,8 +1057,8 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio //Keep track of production Per second product.data[city][1] = prod * producableFrac / (SecsPerMarketCycle * marketCycles); break; - - case "SALE": + } + case "SALE": { //Process sale of Products product.pCost = 0; //Estimated production cost for (var reqMatName in product.reqMats) { @@ -1174,7 +1166,7 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio product.data[city][2] = 0; //data[2] is sell property } break; - + } case "START": case "PURCHASE": case "EXPORT": @@ -1199,10 +1191,9 @@ Industry.prototype.discontinueProduct = function(product) { } Industry.prototype.upgrade = function(upgrade, refs) { - var corporation = refs.corporation, division = refs.division, - office = refs.office; - var upgN = upgrade[0], basePrice = upgrade[1], priceMult = upgrade[2], - upgradeBenefit = upgrade[3]; + var corporation = refs.corporation; + var office = refs.office; + var upgN = upgrade[0]; while (this.upgrades.length <= upgN) {this.upgrades.push(0);} ++this.upgrades[upgN]; @@ -1374,9 +1365,6 @@ Industry.prototype.createResearchBox = function() { }, } - // Construct the tree with Treant - const treantTree = new Treant(markup); - // Add Event Listeners for all Nodes const allResearch = researchTree.getAllNodes(); for (let i = 0; i < allResearch.length; ++i) { @@ -1620,7 +1608,7 @@ var OfficeSpaceTiers = { Basic: "Basic", Enhanced: "Enhanced", Luxurious: "Luxurious", - Extravagant: "Extravagant" + Extravagant: "Extravagant", } function OfficeSpace(params={}) { @@ -1658,7 +1646,7 @@ OfficeSpace.prototype.atCapacity = function() { } OfficeSpace.prototype.process = function(marketCycles=1, parentRefs) { - var corporation = parentRefs.corporation, industry = parentRefs.industry; + var industry = parentRefs.industry; // HRBuddy AutoRecruitment and training if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) { @@ -1741,7 +1729,6 @@ OfficeSpace.prototype.calculateEmployeeProductivity = function(parentRefs) { //Takes care of UI as well OfficeSpace.prototype.findEmployees = function(parentRefs) { - var company = parentRefs.corporation, division = parentRefs.industry; if (this.atCapacity()) { return; } if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) {return;} @@ -1800,7 +1787,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) { office.hireEmployee(employee, parentRefs); removeElementById("cmpy-mgmt-hire-employee-popup"); return false; - } + }, }); return div; }; @@ -1812,7 +1799,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) { clickListener:() => { removeElementById("cmpy-mgmt-hire-employee-popup"); return false; - } + }, }); var elems = [text, @@ -1825,7 +1812,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) { } OfficeSpace.prototype.hireEmployee = function(employee, parentRefs) { - var company = parentRefs.corporation, division = parentRefs.industry; + var company = parentRefs.corporation; var yesBtn = yesNoTxtInpBoxGetYesButton(), noBtn = yesNoTxtInpBoxGetNoButton(); yesBtn.innerHTML = "Hire"; @@ -1958,15 +1945,14 @@ Corporation.prototype.storeCycles = function(numCycles=1) { } Corporation.prototype.process = function() { - var corp = this; if (this.storedCycles >= CyclesPerIndustryStateCycle) { const state = this.getState(); const marketCycles = 1; const gameCycles = (marketCycles * CyclesPerIndustryStateCycle); this.storedCycles -= gameCycles; - this.divisions.forEach(function(ind) { - ind.process(marketCycles, state, corp); + this.divisions.forEach((ind) => { + ind.process(marketCycles, state, this); }); // Process cooldowns @@ -2111,7 +2097,7 @@ Corporation.prototype.goPublic = function() { onkeyup:(e) => { e.preventDefault(); if (e.keyCode === KEY.ENTER) {yesBtn.click();} - } + }, }); var br = createElement("br", {}); yesBtn = createElement("a", { @@ -2138,7 +2124,7 @@ Corporation.prototype.goPublic = function() { dialogBoxCreate(`You took your ${this.name} public and earned ` + `${numeralWrapper.formatMoney(numShares * initialSharePrice)} in your IPO`); return false; - } + }, }); var noBtn = createElement("a", { class:"a-link-button", @@ -2146,7 +2132,7 @@ Corporation.prototype.goPublic = function() { clickListener:() => { removeElementById(goPublicPopupId); return false; - } + }, }); createPopup(goPublicPopupId, [txt, br, input, yesBtn, noBtn]); } @@ -2208,7 +2194,6 @@ Corporation.prototype.calculateShareSale = function(numShares) { Corporation.prototype.convertCooldownToString = function(cd) { // The cooldown value is based on game cycles. Convert to a simple string - const CyclesPerSecond = 1000 / CONSTANTS.MilliPerCycle; const seconds = cd / 5; const SecondsPerMinute = 60; @@ -2351,7 +2336,7 @@ Corporation.prototype.createUI = function() { companyManagementDiv = createElement("div", { id:"cmpy-mgmt-container", position:"fixed", - class:"generic-menupage-container" + class:"generic-menupage-container", }); document.getElementById("entire-game-container").appendChild(companyManagementDiv); diff --git a/src/Corporation/CorporationState.ts b/src/Corporation/CorporationState.ts index adc474496..1a7b2f806 100644 --- a/src/Corporation/CorporationState.ts +++ b/src/Corporation/CorporationState.ts @@ -6,16 +6,10 @@ import { Generic_fromJSON, export const AllCorporationStates: string[] = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"]; export class CorporationState { - // Initiatizes a CorporationState object from a JSON save state. - static fromJSON(value: any): CorporationState { - return Generic_fromJSON(CorporationState, value.data); - } // Number representing what state the Corporation is in. The number // is an index for the array that holds all Corporation States - state: number = 0; - - constructor() {} + state = 0; // Get the name of the current state // NOTE: This does NOT return the number stored in the 'state' property, @@ -40,6 +34,12 @@ export class CorporationState { toJSON(): any { return Generic_toJSON("CorporationState", this); } + + // Initiatizes a CorporationState object from a JSON save state. + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): CorporationState { + return Generic_fromJSON(CorporationState, value.data); + } } Reviver.constructors.CorporationState = CorporationState; diff --git a/src/Corporation/IndustryData.ts b/src/Corporation/IndustryData.ts index f085f7bcc..a7154026f 100644 --- a/src/Corporation/IndustryData.ts +++ b/src/Corporation/IndustryData.ts @@ -4,8 +4,6 @@ import { getBaseResearchTreeCopy, import { numeralWrapper } from "../ui/numeralFormat"; -import { Reviver } from "../../utils/JSONReviver"; - interface IIndustryMap { Energy: T; Utilities: T; @@ -107,7 +105,7 @@ export const IndustryDescriptions: IIndustryMap = { // Map of available Research for each Industry. This data is held in a // ResearchTree object -export let IndustryResearchTrees: IIndustryMap = { +export const IndustryResearchTrees: IIndustryMap = { Energy: getBaseResearchTreeCopy(), Utilities: getBaseResearchTreeCopy(), Agriculture: getBaseResearchTreeCopy(), @@ -124,7 +122,7 @@ export let IndustryResearchTrees: IIndustryMap = { RealEstate: getProductIndustryResearchTreeCopy(), } -export function resetIndustryResearchTrees() { +export function resetIndustryResearchTrees(): void { IndustryResearchTrees.Energy = getBaseResearchTreeCopy(); IndustryResearchTrees.Utilities = getBaseResearchTreeCopy(); IndustryResearchTrees.Agriculture = getBaseResearchTreeCopy(); diff --git a/src/Corporation/IndustryUpgrades.ts b/src/Corporation/IndustryUpgrades.ts index 71b0d7ff7..d83ada87f 100644 --- a/src/Corporation/IndustryUpgrades.ts +++ b/src/Corporation/IndustryUpgrades.ts @@ -11,5 +11,5 @@ export const IndustryUpgrades: IMap = { "this upgrade grants your company a static increase of 3 and 1 to its awareness and " + "popularity, respectively. It will then increase your company's awareness by 1%, and its popularity " + "by a random percentage between 1% and 3%. These effects are increased by other upgrades " + - "that increase the power of your advertising."] + "that increase the power of your advertising."], } diff --git a/src/Corporation/Material.ts b/src/Corporation/Material.ts index abf4bb86b..29a165dd7 100644 --- a/src/Corporation/Material.ts +++ b/src/Corporation/Material.ts @@ -7,56 +7,52 @@ interface IConstructorParams { } export class Material { - // Initiatizes a Material object from a JSON save state. - static fromJSON(value: any): Material { - return Generic_fromJSON(Material, value.data); - } // Name of material - name: string = "InitName"; + name = "InitName"; // Amount of material owned - qty: number = 0; + qty = 0; // Material's "quality". Unbounded - qlt: number = 0; + qlt = 0; // How much demand the Material has in the market, and the range of possible // values for this "demand" - dmd: number = 0; + dmd = 0; dmdR: number[] = [0, 0]; // How much competition there is for this Material in the market, and the range // of possible values for this "competition" - cmp: number = 0; + cmp = 0; cmpR: number[] = [0, 0]; // Maximum volatility of this Materials stats - mv: number = 0; + mv = 0; // Markup. Determines how high of a price you can charge on the material // compared to the market price without suffering loss in # of sales // Quality is divided by this to determine markup limits // e,g, If mku is 10 and quality is 100 then you can markup prices by 100/10 = 10 - mku: number = 0; + mku = 0; // How much of this material is being bought, sold, imported and produced every second - buy: number = 0; - sll: number = 0; - prd: number = 0; - imp: number = 0; + buy = 0; + sll = 0; + prd = 0; + imp = 0; // Exports of this material to another warehouse/industry exp: any[] = []; // Total amount of this material exported in the last cycle - totalExp: number = 0; + totalExp = 0; // Cost / sec to buy this material. AKA Market Price - bCost: number = 0; + bCost = 0; // Cost / sec to sell this material - sCost: number = 0; + sCost = 0; // Flags to keep track of whether production and/or sale of this material is limited // [Whether production/sale is limited, limit amount] @@ -64,9 +60,9 @@ export class Material { sllman: any[] = [false, 0]; // Sale // Flags that signal whether automatic sale pricing through Market TA is enabled - marketTa1: boolean = false; - marketTa2: boolean = false; - marketTa2Price: number = 0; + marketTa1 = false; + marketTa2 = false; + marketTa2Price = 0; constructor(params: IConstructorParams = {}) { if (params.name) { this.name = params.name; } @@ -166,7 +162,7 @@ export class Material { const compChange: number = 1 + compVolatility; if (Math.random() < 0.5) { this.cmp *= compChange; - if (this.cmp > this.cmpR[1]) {this.cmp = this.cmpR[1]}; + if (this.cmp > this.cmpR[1]) {this.cmp = this.cmpR[1]} this.bCost *= (1 / priceChange); // Competition increases, so price goes down } else { this.cmp *= (1 / compChange); @@ -192,6 +188,12 @@ export class Material { toJSON(): any { return Generic_toJSON("Material", this); } + + // Initiatizes a Material object from a JSON save state. + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Material { + return Generic_fromJSON(Material, value.data); + } } Reviver.constructors.Material = Material; diff --git a/src/Corporation/Product.ts b/src/Corporation/Product.ts index 902b0015b..974f8e4a9 100644 --- a/src/Corporation/Product.ts +++ b/src/Corporation/Product.ts @@ -42,49 +42,45 @@ interface IIndustry { export class Product { - // Initiatizes a Product object from a JSON save state. - static fromJSON(value: any): Product { - return Generic_fromJSON(Product, value.data); - } // Product name - name: string = ""; + name = ""; // The demand for this Product in the market. Gradually decreases - dmd: number = 0; + dmd = 0; // How much competition there is in the market for this Product - cmp: number = 0; + cmp = 0; // Markup. Affects how high of a price you can charge for this Product // without suffering a loss in the # of sales - mku: number = 0; + mku = 0; // Production cost - estimation of how much money it costs to make this Product - pCost: number = 0; + pCost = 0; // Sell cost - sCost: number = 0; + sCost = 0; // Variables for handling the creation process of this Product - fin: boolean = false; // Whether this Product has finished being created - prog: number = 0; // Creation progress - A number betwee 0-100 representing percentage - createCity: string = ""; // City in which the product is/was being created - designCost: number = 0; // How much money was invested into designing this Product - advCost: number = 0; // How much money was invested into advertising this Product + fin = false; // Whether this Product has finished being created + prog = 0; // Creation progress - A number betwee 0-100 representing percentage + createCity = ""; // City in which the product is/was being created + designCost = 0; // How much money was invested into designing this Product + advCost = 0; // How much money was invested into advertising this Product // Aggregate score for this Product's 'rating' // This is based on the stats/properties below. The weighting of the // stats/properties below differs between different industries - rat: number = 0; + rat = 0; // Stats/properties of this Product - qlt: number = 0; - per: number = 0; - dur: number = 0; - rel: number = 0; - aes: number = 0; - fea: number = 0; + qlt = 0; + per = 0; + dur = 0; + rel = 0; + aes = 0; + fea = 0; // Data refers to the production, sale, and quantity of the products // These values are specific to a city @@ -93,11 +89,11 @@ export class Product { // Location of this Product // Only applies for location-based products like restaurants/hospitals - loc: string = ""; + loc = ""; // How much space 1 unit of the Product takes (in the warehouse) // Not applicable for all Products - siz: number = 0; + siz = 0; // Material requirements. An object that maps the name of a material to how much it requires // to make 1 unit of the product. @@ -110,8 +106,8 @@ export class Product { sllman: IMap = createCityMap([false, 0]); // Flags that signal whether automatic sale pricing through Market TA is enabled - marketTa1: boolean = false; - marketTa2: boolean = false; + marketTa1 = false; + marketTa2 = false; marketTa2Price: IMap = createCityMap(0); constructor(params: IConstructorParams={}) { @@ -135,7 +131,7 @@ export class Product { // empWorkMult is a multiplier that increases progress rate based on // productivity of employees - createProduct(marketCycles: number=1, empWorkMult: number=1): void { + createProduct(marketCycles=1, empWorkMult=1): void { if (this.fin) { return; } this.prog += (marketCycles * .01 * empWorkMult); } @@ -145,18 +141,18 @@ export class Product { this.fin = true; //Calculate properties - var progrMult = this.prog / 100; + const progrMult = this.prog / 100; const engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"]; const mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"]; const rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"]; const opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"]; const busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"]; - var designMult = 1 + (Math.pow(this.designCost, 0.1) / 100); - var balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) + + const designMult = 1 + (Math.pow(this.designCost, 0.1) / 100); + const balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) + (1.5 * opsRatio) + (busRatio); - var sciMult = 1 + (Math.pow(industry.sciResearch.qty, industry.sciFac) / 800); - var totalMult = progrMult * balanceMult * designMult * sciMult; + const sciMult = 1 + (Math.pow(industry.sciResearch.qty, industry.sciFac) / 800); + const totalMult = progrMult * balanceMult * designMult * sciMult; this.qlt = totalMult * ((0.10 * employeeProd[EmployeePositions.Engineer]) + (0.05 * employeeProd[EmployeePositions.Management]) + @@ -189,14 +185,14 @@ export class Product { (0.05 * employeeProd[EmployeePositions.Operations]) + (0.05 * employeeProd[EmployeePositions.Business])); this.calculateRating(industry); - var advMult = 1 + (Math.pow(this.advCost, 0.1) / 100); + const advMult = 1 + (Math.pow(this.advCost, 0.1) / 100); this.mku = 100 / (advMult * Math.pow((this.qlt + 0.001), 0.65) * (busRatio + mgmtRatio)); this.dmd = industry.awareness === 0 ? 20 : Math.min(100, advMult * (100 * (industry.popularity / industry.awareness))); this.cmp = getRandomInt(0, 70); //Calculate the product's required materials //For now, just set it to be the same as the requirements to make materials - for (var matName in industry.reqMats) { + for (const matName in industry.reqMats) { if (industry.reqMats.hasOwnProperty(matName)) { this.reqMats[matName] = industry.reqMats[matName]; } @@ -205,7 +201,7 @@ export class Product { //Calculate the product's size //For now, just set it to be the same size as the requirements to make materials this.siz = 0; - for (var matName in industry.reqMats) { + for (const matName in industry.reqMats) { this.siz += MaterialSizes[matName] * industry.reqMats[matName]; } @@ -240,6 +236,12 @@ export class Product { toJSON(): any { return Generic_toJSON("Product", this); } + + // Initiatizes a Product object from a JSON save state. + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Product { + return Generic_fromJSON(Product, value.data); + } } Reviver.constructors.Product = Product; diff --git a/src/Corporation/ProductRatingWeights.ts b/src/Corporation/ProductRatingWeights.ts index e19e9298d..8459fa6bf 100644 --- a/src/Corporation/ProductRatingWeights.ts +++ b/src/Corporation/ProductRatingWeights.ts @@ -10,7 +10,7 @@ export interface IProductRatingWeight { Reliability?: number; } -export const ProductRatingWeights: IMap = { +export const ProductRatingWeights: IMap = { [Industries.Food]: { Quality: 0.7, Durability: 0.1, @@ -73,5 +73,5 @@ export const ProductRatingWeights: IMap = { Reliability: 0.1, Aesthetics: 0.35, Features: 0.1, - } + }, } diff --git a/src/Corporation/Research.ts b/src/Corporation/Research.ts index ee017ec06..6c370e8ab 100644 --- a/src/Corporation/Research.ts +++ b/src/Corporation/Research.ts @@ -16,25 +16,25 @@ export interface IConstructorParams { export class Research { // Name of research. This will be used to identify researches in the Research Tree - name: string = ""; + name = ""; // How much scientific research it costs to unlock this - cost: number = 0; + cost = 0; // Description of what the Research does - desc: string = ""; + desc = ""; // All possible generic upgrades for the company, in the form of multipliers - advertisingMult: number = 1; - employeeChaMult: number = 1; - employeeCreMult: number = 1; - employeeEffMult: number = 1; - employeeIntMult: number = 1; - productionMult: number = 1; - productProductionMult: number = 1; - salesMult: number = 1; - sciResearchMult: number = 1; - storageMult: number = 1; + advertisingMult = 1; + employeeChaMult = 1; + employeeCreMult = 1; + employeeEffMult = 1; + employeeIntMult = 1; + productionMult = 1; + productProductionMult = 1; + salesMult = 1; + sciResearchMult = 1; + storageMult = 1; constructor(p: IConstructorParams={name: "", cost: 0, desc: ""}) { this.name = p.name; diff --git a/src/Corporation/ResearchMap.ts b/src/Corporation/ResearchMap.ts index b38b8356b..0159c3283 100644 --- a/src/Corporation/ResearchMap.ts +++ b/src/Corporation/ResearchMap.ts @@ -5,9 +5,9 @@ import { Research, import { researchMetadata } from "./data/ResearchMetadata"; import { IMap } from "../types"; -export let ResearchMap: IMap = {}; +export const ResearchMap: IMap = {}; -function addResearch(p: IConstructorParams) { +function addResearch(p: IConstructorParams): void { if (ResearchMap[p.name] != null) { console.warn(`Duplicate Research being defined: ${p.name}`); } diff --git a/src/Corporation/ResearchTree.ts b/src/Corporation/ResearchTree.ts index 8414631c8..c55a62e43 100644 --- a/src/Corporation/ResearchTree.ts +++ b/src/Corporation/ResearchTree.ts @@ -26,10 +26,10 @@ export class Node { // How much Scientific Research is needed for this // Necessary to show it on the UI - cost: number = 0; + cost = 0; // Whether or not this Research has been unlocked - researched: boolean = false; + researched = false; // Parent node in the tree // The parent node defines the prerequisite Research (there can only be one) @@ -37,7 +37,7 @@ export class Node { parent: Node | null = null; // Name of the Research held in this Node - text: string = ""; + text = ""; constructor(p: IConstructorParams = {cost: 0, text: ""}) { if (ResearchMap[p.text] == null) { @@ -56,21 +56,21 @@ export class Node { } } - addChild(n: Node) { + addChild(n: Node): void { this.children.push(n); n.parent = this; } // Return an object that describes a TreantJS-compatible markup/config for this Node // See: http://fperucic.github.io/treant-js/ - createTreantMarkup(): object { + createTreantMarkup(): any { const childrenArray = []; for (let i = 0; i < this.children.length; ++i) { childrenArray.push(this.children[i].createTreantMarkup()); } // Determine what css class this Node should have in the diagram - let htmlClass: string = ""; + let htmlClass = ""; if (this.researched) { htmlClass = "researched"; } else if (this.parent && this.parent.researched === false) { @@ -109,7 +109,7 @@ export class Node { return null; } - setParent(n: Node) { + setParent(n: Node): void { this.parent = n; } } @@ -124,11 +124,9 @@ export class ResearchTree { // Root Node root: Node | null = null; - constructor() {} - // Return an object that contains a Tree markup for TreantJS (using the JSON approach) // See: http://fperucic.github.io/treant-js/ - createTreantMarkup(): object { + createTreantMarkup(): any { if (this.root == null) { return {}; } const treeMarkup = this.root.createTreantMarkup(); @@ -205,7 +203,7 @@ export class ResearchTree { // Helper function for all the multiplier getter fns getMultiplierHelper(propName: string): number { - let res: number = 1; + let res = 1; if (this.root == null) { return res; } const queue: Node[] = []; diff --git a/src/Corporation/Warehouse.ts b/src/Corporation/Warehouse.ts index 15bdf03b6..ec912fa28 100644 --- a/src/Corporation/Warehouse.ts +++ b/src/Corporation/Warehouse.ts @@ -19,17 +19,13 @@ interface IConstructorParams { } export class Warehouse { - // Initiatizes a Warehouse object from a JSON save state. - static fromJSON(value: any): Warehouse { - return Generic_fromJSON(Warehouse, value.data); - } // Text that describes how the space in this Warehouse is being used // Used to create a tooltip in the UI - breakdown: string = ""; + breakdown = ""; // Warehouse's level, which affects its maximum size - level: number = 1; + level = 1; // City that this Warehouse is in loc: string; @@ -41,19 +37,19 @@ export class Warehouse { size: number; // Amount of space currently used by warehouse - sizeUsed: number = 0; + sizeUsed = 0; // Whether Smart Supply is enabled for this Industry (the Industry that this Warehouse is for) - smartSupplyEnabled: boolean = false; + smartSupplyEnabled = false; // Flag that indicates whether Smart Supply accounts for imports when calculating // the amount fo purchase - smartSupplyConsiderExports: boolean = false; + smartSupplyConsiderExports = false; // Stores the amount of product to be produced. Used for Smart Supply unlock. // The production tracked by smart supply is always based on the previous cycle, // so it will always trail the "true" production by 1 cycle - smartSupplyStore: number = 0; + smartSupplyStore = 0; constructor(params: IConstructorParams = {}) { this.loc = params.loc ? params.loc : ""; @@ -70,7 +66,7 @@ export class Warehouse { Drugs: new Material({name: "Drugs"}), Robots: new Material({name: "Robots"}), AICores: new Material({name: "AI Cores"}), - RealEstate: new Material({name: "Real Estate"}) + RealEstate: new Material({name: "Real Estate"}), } if (params.corp && params.industry) { @@ -79,11 +75,11 @@ export class Warehouse { } // Re-calculate how much space is being used by this Warehouse - updateMaterialSizeUsed() { + updateMaterialSizeUsed(): void { this.sizeUsed = 0; this.breakdown = ""; for (const matName in this.materials) { - var mat = this.materials[matName]; + const mat = this.materials[matName]; if (MaterialSizes.hasOwnProperty(matName)) { this.sizeUsed += (mat.qty * MaterialSizes[matName]); if (mat.qty > 0) { @@ -96,7 +92,7 @@ export class Warehouse { } } - updateSize(corporation: IParent, industry: IParent) { + updateSize(corporation: IParent, industry: IParent): void { try { this.size = (this.level * 100) * corporation.getStorageMultiplier() @@ -110,6 +106,12 @@ export class Warehouse { toJSON(): any { return Generic_toJSON("Warehouse", this); } + + // Initiatizes a Warehouse object from a JSON save state. + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Warehouse { + return Generic_fromJSON(Warehouse, value.data); + } } Reviver.constructors.Warehouse = Warehouse; diff --git a/src/Corporation/data/ResearchMetadata.ts b/src/Corporation/data/ResearchMetadata.ts index e19d730b2..921989bb8 100644 --- a/src/Corporation/data/ResearchMetadata.ts +++ b/src/Corporation/data/ResearchMetadata.ts @@ -82,7 +82,7 @@ export const researchMetadata: IConstructorParams[] = [ cost: 15e3, desc: "Use automated software to handle the hiring of employees. With this " + "research, each office will automatically hire one employee per " + - "market cycle if there is available space." + "market cycle if there is available space.", }, { @@ -90,7 +90,7 @@ export const researchMetadata: IConstructorParams[] = [ cost: 20e3, desc: "Use automated software to handle the training of employees. With this " + "research, each employee hired with HRBuddy-Recruitment will automatically " + - "be assigned to 'Training', rather than being unassigned." + "be assigned to 'Training', rather than being unassigned.", }, { name: "JoyWire", diff --git a/src/Corporation/ui/BaseReactComponent.js b/src/Corporation/ui/BaseReactComponent.js index a6b5d2f9d..b3da9a6fc 100644 --- a/src/Corporation/ui/BaseReactComponent.js +++ b/src/Corporation/ui/BaseReactComponent.js @@ -17,6 +17,4 @@ export class BaseReactComponent extends Component { routing() { return this.props.routing; } - - render() {} } diff --git a/src/Corporation/ui/CorporationUIEventHandler.js b/src/Corporation/ui/CorporationUIEventHandler.js index 0d1eaa336..06ad8af6c 100644 --- a/src/Corporation/ui/CorporationUIEventHandler.js +++ b/src/Corporation/ui/CorporationUIEventHandler.js @@ -16,7 +16,7 @@ import { Corporation, import { Industries, IndustryStartingCosts, IndustryDescriptions, - IndustryResearchTrees } from "../IndustryData"; +} from "../IndustryData"; import { MaterialSizes } from "../MaterialSizes"; @@ -61,13 +61,13 @@ export class CorporationEventHandler { createBribeFactionsPopup() { const popupId = "cmpy-mgmt-bribe-factions-popup"; const txt = createElement("p", { - innerText:"You can use Corporation funds or stock shares to bribe Faction Leaders in exchange for faction reputation" + innerText:"You can use Corporation funds or stock shares to bribe Faction Leaders in exchange for faction reputation", }); const factionSelector = createElement("select", { margin:"3px" }); for (let i = 0; i < Player.factions.length; ++i) { const facName = Player.factions[i]; factionSelector.add(createElement("option", { - text: facName, value: facName + text: facName, value: facName, })); } var repGainText = createElement("p"); @@ -93,7 +93,7 @@ export class CorporationEventHandler { factionSelector.options[factionSelector.selectedIndex].value + " with this bribe"; } - } + }, }); stockSharesInput = createElement("input", { type:"number", placeholder:"Stock Shares", margin: "5px", @@ -115,7 +115,7 @@ export class CorporationEventHandler { factionSelector.options[factionSelector.selectedIndex].value + " with this bribe"; } - } + }, }); var confirmButton = createElement("button", { class:"a-link-button", innerText:"Bribe", display:"inline-block", @@ -145,7 +145,7 @@ export class CorporationEventHandler { removeElementById(popupId); return false; } - } + }, }); const cancelButton = createPopupCloseButton(popupId, { class: "std-button", @@ -187,7 +187,7 @@ export class CorporationEventHandler { costIndicator.innerText = "Purchase " + numShares + " shares for a total of " + numeralWrapper.format(numShares * buybackPrice, '$0.000a'); } - } + }, }); var confirmBtn = createElement("button", { class:"a-link-button", innerText:"Buy shares", display:"inline-block", @@ -221,7 +221,7 @@ export class CorporationEventHandler { } return false; - } + }, }); var cancelBtn = createPopupCloseButton(popupId, { class: "std-button", @@ -249,7 +249,7 @@ export class CorporationEventHandler { removeElementById(popupId); this.rerender(); return false; - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); @@ -264,7 +264,7 @@ export class CorporationEventHandler { const exportTxt = createElement("p", { innerText:"Select the industry and city to export this material to, as well as " + "how much of this material to export per second. You can set the export " + - "amount to 'MAX' to export all of the materials in this warehouse." + "amount to 'MAX' to export all of the materials in this warehouse.", }); //Select industry and city to export to @@ -286,7 +286,7 @@ export class CorporationEventHandler { return; } } - } + }, }); for (let i = 0; i < corp.divisions.length; ++i) { @@ -299,7 +299,7 @@ export class CorporationEventHandler { //Select amount to export const exportAmount = createElement("input", { class: "text-input", - placeholder:"Export amount / s" + placeholder:"Export amount / s", }); const exportBtn = createElement("button", { @@ -328,14 +328,14 @@ export class CorporationEventHandler { mat.exp.push(exportObj); removeElementById(popupId); return false; - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); const currExportsText = createElement("p", { innerText:"Below is a list of all current exports of this material from this warehouse. " + - "Clicking on one of the exports below will REMOVE that export." + "Clicking on one of the exports below will REMOVE that export.", }); const currExports = []; for (var i = 0; i < mat.exp.length; ++i) { @@ -349,7 +349,7 @@ export class CorporationEventHandler { mat.exp.splice(i, 1); //Remove export object removeElementById(popupId); createExportMaterialPopup(mat); - } + }, })); })(i, mat, currExports); } @@ -385,7 +385,7 @@ export class CorporationEventHandler { onkeyup: (e) => { e.preventDefault(); if (e.keyCode === KEY.ENTER) {allocateBtn.click();} - } + }, }); allocateBtn = createElement("button", { @@ -404,7 +404,7 @@ export class CorporationEventHandler { this.rerender(); return false; - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { @@ -478,7 +478,7 @@ export class CorporationEventHandler { } else { updateDynamicText(this.corp); } - } + }, }); issueBtn = createElement("button", { @@ -523,7 +523,7 @@ export class CorporationEventHandler { this.rerender(); return false; - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { @@ -541,7 +541,7 @@ export class CorporationEventHandler { const popupId = "cmpy-mgmt-limit-product-production-popup"; const txt = createElement("p", { innerText:"Enter a limit to the amount of this product you would " + - "like to product per second. Leave the box empty to set no limit." + "like to product per second. Leave the box empty to set no limit.", }); let confirmBtn; const input = createElement("input", { @@ -551,7 +551,7 @@ export class CorporationEventHandler { onkeyup: (e) => { e.preventDefault(); if (e.keyCode === KEY.ENTER) { confirmBtn.click(); } - } + }, }); confirmBtn = createElement("button", { class: "std-button", @@ -578,7 +578,7 @@ export class CorporationEventHandler { removeElementById(popupId); this.rerender(); return false; - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); cancelBtn.style.margin = "6px"; @@ -600,7 +600,7 @@ export class CorporationEventHandler { if (division.offices[cityName] instanceof OfficeSpace) { designCity.add(createElement("option", { value: cityName, - text: cityName + text: cityName, })); } } @@ -630,7 +630,7 @@ export class CorporationEventHandler { onkeyup: (e) => { e.preventDefault(); if (e.keyCode === KEY.ENTER) { confirmBtn.click(); } - } + }, }); confirmBtn = createElement("button", { class: "std-button", @@ -665,7 +665,7 @@ export class CorporationEventHandler { } this.rerender(); return false; - } + }, }) const cancelBtn = createPopupCloseButton(popupId, { class: "std-button", @@ -679,8 +679,6 @@ export class CorporationEventHandler { // Create a popup that lets the player use the Market TA research for Materials createMaterialMarketTaPopup(mat, industry) { - const corp = this.corp; - const popupId = "cmpy-mgmt-marketta-popup"; const markupLimit = mat.getMarkupLimit(); const ta1 = createElement("p", { @@ -699,7 +697,7 @@ export class CorporationEventHandler { for: useTa1AutoSaleId, innerText: "Use Market-TA.I for Auto-Sale Price", tooltip: "If this is enabled, then this Material will automatically " + - "be sold at the price identified by Market-TA.I (i.e. the price shown above)" + "be sold at the price identified by Market-TA.I (i.e. the price shown above)", }) const useTa1AutoSaleCheckbox = createElement("input", { checked: mat.marketTa1, @@ -708,7 +706,7 @@ export class CorporationEventHandler { type: "checkbox", changeListener: (e) => { mat.marketTa1 = e.target.checked; - } + }, }); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox); @@ -766,7 +764,7 @@ export class CorporationEventHandler { tooltip: "If this is enabled, then this Material will automatically " + "be sold at the optimal price such that the amount sold matches the " + "amount produced. (i.e. the highest possible price, while still ensuring " + - " that all produced materials will be sold)" + " that all produced materials will be sold)", }) const useTa2AutoSaleCheckbox = createElement("input", { checked: mat.marketTa2, @@ -775,14 +773,14 @@ export class CorporationEventHandler { type: "checkbox", changeListener: (e) => { mat.marketTa2 = e.target.checked; - } + }, }); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox); const ta2OverridesTa1 = createElement("p", { innerText: "Note that Market-TA.II overrides Market-TA.I. This means that if " + - "both are enabled, then Market-TA.II will take effect, not Market-TA.I" + "both are enabled, then Market-TA.II will take effect, not Market-TA.I", }); createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]); @@ -805,7 +803,7 @@ export class CorporationEventHandler { if (!(division.offices[cityName] instanceof OfficeSpace)) { citySelector.add(createElement("option", { text: cityName, - value: cityName + value: cityName, })); } } @@ -832,7 +830,7 @@ export class CorporationEventHandler { removeElementById(popupId); this.rerender(); return false; - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { class: "std-button", @@ -852,7 +850,7 @@ export class CorporationEventHandler { innerHTML: "Create a new division to expand into a new industry:", }); var selector = createElement("select", { - class:"dropdown" + class:"dropdown", }); var industryDescription = createElement("p", {}); var yesBtn; @@ -866,11 +864,11 @@ export class CorporationEventHandler { onkeyup:(e)=>{ e.preventDefault(); if (e.keyCode === KEY.ENTER) {yesBtn.click();} - } + }, }); var nameLabel = createElement("label", { for:"cmpy-mgmt-expand-industry-name-input", - innerText:"Division name: " + innerText:"Division name: ", }); yesBtn = createElement("span", { class:"popup-box-button", @@ -905,7 +903,7 @@ export class CorporationEventHandler { this.rerender(); } return false; - } + }, }); const noBtn = createPopupCloseButton(popupId, { @@ -923,7 +921,7 @@ export class CorporationEventHandler { // Have Agriculture be first as recommended option if (!ownedIndustries["Agriculture"]) { selector.add(createElement("option", { - text:Industries["Agriculture"], value:"Agriculture" + text:Industries["Agriculture"], value:"Agriculture", })); } @@ -964,8 +962,6 @@ export class CorporationEventHandler { // Create a popup that lets the player use the Market TA research for Products createProductMarketTaPopup(product, industry) { - const corp = this.corp; - const popupId = "cmpy-mgmt-marketta-popup"; const markupLimit = product.rat / product.mku; const ta1 = createElement("p", { @@ -984,7 +980,7 @@ export class CorporationEventHandler { for: useTa1AutoSaleId, innerText: "Use Market-TA.I for Auto-Sale Price", tooltip: "If this is enabled, then this Product will automatically " + - "be sold at the price identified by Market-TA.I (i.e. the price shown above)" + "be sold at the price identified by Market-TA.I (i.e. the price shown above)", }) const useTa1AutoSaleCheckbox = createElement("input", { checked: product.marketTa1, @@ -993,7 +989,7 @@ export class CorporationEventHandler { type: "checkbox", changeListener: (e) => { product.marketTa1 = e.target.checked; - } + }, }); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox); @@ -1043,7 +1039,7 @@ export class CorporationEventHandler { tooltip: "If this is enabled, then this Product will automatically " + "be sold at the optimal price such that the amount sold matches the " + "amount produced. (i.e. the highest possible price, while still ensuring " + - " that all produced materials will be sold)" + " that all produced materials will be sold)", }) const useTa2AutoSaleCheckbox = createElement("input", { checked: product.marketTa2, @@ -1052,14 +1048,14 @@ export class CorporationEventHandler { type: "checkbox", changeListener: (e) => { product.marketTa2 = e.target.checked; - } + }, }); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox); const ta2OverridesTa1 = createElement("p", { innerText: "Note that Market-TA.II overrides Market-TA.I. This means that if " + - "both are enabled, then Market-TA.II will take effect, not Market-TA.I" + "both are enabled, then Market-TA.II will take effect, not Market-TA.I", }); createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]); @@ -1076,7 +1072,7 @@ export class CorporationEventHandler { const purchasePopupId = "cmpy-mgmt-material-purchase-popup"; const txt = createElement("p", { innerHTML: "Enter the amount of " + mat.name + " you would like " + - "to purchase per second. This material's cost changes constantly" + "to purchase per second. This material's cost changes constantly", }); let confirmBtn; let input = createElement("input", { @@ -1087,7 +1083,7 @@ export class CorporationEventHandler { onkeyup: (e) => { e.preventDefault(); if (e.keyCode === KEY.ENTER) {confirmBtn.click();} - } + }, }); confirmBtn = createElement("button", { innerText: "Confirm", class: "std-button", @@ -1101,7 +1097,7 @@ export class CorporationEventHandler { this.rerender(); return false; } - } + }, }); const clearButton = createElement("button", { innerText: "Clear Purchase", class: "std-button", @@ -1110,7 +1106,7 @@ export class CorporationEventHandler { removeElementById(purchasePopupId); this.rerender(); return false; - } + }, }); const cancelBtn = createPopupCloseButton(purchasePopupId, { class: "std-button", @@ -1153,7 +1149,7 @@ export class CorporationEventHandler { e.preventDefault(); updateBulkPurchaseText(e.target.value); if (e.keyCode === KEY.ENTER) {bulkPurchaseConfirmBtn.click();} - } + }, }); bulkPurchaseConfirmBtn = createElement("button", { @@ -1184,7 +1180,7 @@ export class CorporationEventHandler { removeElementById(purchasePopupId); return false; } - } + }, }) elems.push(bulkPurchaseInfo); @@ -1224,7 +1220,7 @@ export class CorporationEventHandler { onkeyup: (e) => { e.preventDefault(); if (e.keyCode === KEY.ENTER) {confirmBtn.click();} - } + }, }); let inputButtonInitValue = mat.sCost ? mat.sCost : null; @@ -1241,7 +1237,7 @@ export class CorporationEventHandler { onkeyup: (e) => { e.preventDefault(); if (e.keyCode === KEY.ENTER) {confirmBtn.click();} - } + }, }); confirmBtn = createElement("button", { class: "std-button", @@ -1307,7 +1303,7 @@ export class CorporationEventHandler { removeElementById(sellPopupId); this.rerender(); return false; - } + }, }); const cancelBtn = createPopupCloseButton(sellPopupId, { class: "std-button", @@ -1347,7 +1343,7 @@ export class CorporationEventHandler { onkeyup: (e) => { e.preventDefault(); if (e.keyCode === KEY.ENTER) {confirmBtn.click();} - } + }, }); let inputButtonInitValue = product.sCost ? product.sCost : null; @@ -1365,7 +1361,7 @@ export class CorporationEventHandler { onkeyup: (e) => { e.preventDefault(); if (e.keyCode === KEY.ENTER) {confirmBtn.click();} - } + }, }); const checkboxDiv = createElement("div", { border: "1px solid white", @@ -1478,7 +1474,7 @@ export class CorporationEventHandler { removeElementById(popupId); this.rerender(); return false; - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { class: "std-button" }); @@ -1515,12 +1511,10 @@ export class CorporationEventHandler { } else { const stockSaleResults = this.corp.calculateShareSale(numShares); const profit = stockSaleResults[0]; - const newSharePrice = stockSaleResults[1]; - const newSharesUntilUpdate = stockSaleResults[2]; profitIndicator.innerText = "Sell " + numShares + " shares for a total of " + numeralWrapper.format(profit, '$0.000a'); } - } + }, }); const confirmBtn = createElement("button", { class:"a-link-button", innerText:"Sell shares", display:"inline-block", @@ -1562,7 +1556,7 @@ export class CorporationEventHandler { return false; } - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { class: "std-button", @@ -1579,10 +1573,10 @@ export class CorporationEventHandler { const popupId = "cmpy-mgmt-throw-office-party-popup"; const txt = createElement("p", { innerText:"Enter the amount of money you would like to spend PER EMPLOYEE " + - "on this office party" + "on this office party", }); const totalCostTxt = createElement("p", { - innerText:"Throwing this party will cost a total of $0" + innerText:"Throwing this party will cost a total of $0", }); let confirmBtn; const input = createElement("input", { @@ -1598,7 +1592,7 @@ export class CorporationEventHandler { onkeyup:(e)=>{ e.preventDefault(); if (e.keyCode === KEY.ENTER) {confirmBtn.click();} - } + }, }); confirmBtn = createElement("button", { class: "std-button", @@ -1622,7 +1616,7 @@ export class CorporationEventHandler { } } return false; - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { class: "std-button", innerText: "Cancel" }); @@ -1661,7 +1655,7 @@ export class CorporationEventHandler { const upgradeCostMax = OfficeInitialCost * mult; const text = createElement("p", { - innerText:"Increase the size of your office space to fit additional employees!" + innerText:"Increase the size of your office space to fit additional employees!", }); const text2 = createElement("p", { innerText: "Upgrade size: " }); @@ -1680,7 +1674,7 @@ export class CorporationEventHandler { } removeElementById(popupId); return false; - } + }, }); const confirmBtn15 = createElement("button", { class: this.corp.funds.lt(upgradeCost15) ? "a-link-button-inactive" : "a-link-button", @@ -1697,7 +1691,7 @@ export class CorporationEventHandler { } removeElementById(popupId); return false; - } + }, }); const confirmBtnMax = createElement("button", { class:this.corp.funds.lt(upgradeCostMax) ? "a-link-button-inactive" : "a-link-button", @@ -1714,7 +1708,7 @@ export class CorporationEventHandler { } removeElementById(popupId); return false; - } + }, }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); cancelBtn.style.margin = "4px"; diff --git a/src/Corporation/ui/HeaderTabs.jsx b/src/Corporation/ui/HeaderTabs.jsx index a0e6fd1da..c2d895d7d 100644 --- a/src/Corporation/ui/HeaderTabs.jsx +++ b/src/Corporation/ui/HeaderTabs.jsx @@ -4,8 +4,6 @@ import React from "react"; import { BaseReactComponent } from "./BaseReactComponent"; -import { overviewPage } from "./Routing"; - function HeaderTab(props) { let className = "cmpy-mgmt-header-tab"; if (props.current) { @@ -71,7 +69,7 @@ export class HeaderTabs extends BaseReactComponent { { this.renderTab({ onClick: this.eventHandler().createNewIndustryPopup.bind(this.eventHandler()), - text: "Expand into new Industry" + text: "Expand into new Industry", }) } diff --git a/src/Corporation/ui/IndustryOffice.jsx b/src/Corporation/ui/IndustryOffice.jsx index 324148733..d43cadf22 100644 --- a/src/Corporation/ui/IndustryOffice.jsx +++ b/src/Corporation/ui/IndustryOffice.jsx @@ -62,7 +62,6 @@ export class IndustryOffice extends BaseReactComponent { // Calculate how many NEW emplyoees we need to account for const currentNumEmployees = office.employees.length; - const newEmployees = currentNumEmployees - this.state.numEmployees; // Record the number of employees in each position, for NEW employees only for (let i = this.state.numEmployees; i < office.employees.length; ++i) { diff --git a/src/Corporation/ui/IndustryOverview.jsx b/src/Corporation/ui/IndustryOverview.jsx index a108fba6d..09cdc6a0a 100644 --- a/src/Corporation/ui/IndustryOverview.jsx +++ b/src/Corporation/ui/IndustryOverview.jsx @@ -12,7 +12,6 @@ import { createProgressBarText } from "../../../utils/helpers/createProgressB export class IndustryOverview extends BaseReactComponent { renderMakeProductButton() { - const corp = this.corp(); const division = this.routing().currentDivision; // Validated inside render() var createProductButtonText, createProductPopupText; @@ -97,7 +96,6 @@ export class IndustryOverview extends BaseReactComponent { const popularity = `Popularity: ${numeralWrapper.format(division.popularity, "0.000")}`; let advertisingInfo = false; - let advertisingTooltip; const advertisingFactors = division.getAdvertisingFactors(); const awarenessFac = advertisingFactors[1]; const popularityFac = advertisingFactors[2]; diff --git a/src/Corporation/ui/IndustryWarehouse.jsx b/src/Corporation/ui/IndustryWarehouse.jsx index f36f451e4..d0f220a56 100644 --- a/src/Corporation/ui/IndustryWarehouse.jsx +++ b/src/Corporation/ui/IndustryWarehouse.jsx @@ -19,7 +19,6 @@ import { isString } from "../../../utils/helpers/isString"; function ProductComponent(props) { const corp = props.corp; const division = props.division; - const warehouse = props.warehouse; const city = props.city; const product = props.product; const eventHandler = props.eventHandler; @@ -203,15 +202,6 @@ function MaterialComponent(props) { // Total gain or loss of this material (per second) const totalGain = mat.buy + mat.prd + mat.imp - mat.sll - mat.totalExp; - // Competition and demand info, if they're unlocked - let cmpAndDmdText = ""; - if (corp.unlockUpgrades[2] === 1) { - cmpAndDmdText += "
    Demand: " + numeralWrapper.format(mat.dmd, nf); - } - if (corp.unlockUpgrades[3] === 1) { - cmpAndDmdText += "
    Competition: " + numeralWrapper.format(mat.cmp, nf); - } - // Flag that determines whether this industry is "new" and the current material should be // marked with flashing-red lights const tutorial = division.newInd && Object.keys(division.reqMats).includes(mat.name) && @@ -511,7 +501,6 @@ export class IndustryWarehouse extends BaseReactComponent { } render() { - const corp = this.corp(); const division = this.routing().currentDivision; if (division == null) { throw new Error(`Routing does not hold reference to the current Industry`); diff --git a/src/Corporation/ui/MainPanel.jsx b/src/Corporation/ui/MainPanel.jsx index 00d48bf33..3a632639c 100644 --- a/src/Corporation/ui/MainPanel.jsx +++ b/src/Corporation/ui/MainPanel.jsx @@ -7,7 +7,6 @@ import { BaseReactComponent } from "./BaseReactComponent"; import { CityTabs } from "./CityTabs"; import { Industry } from "./Industry"; import { Overview } from "./Overview"; -import { overviewPage } from "./Routing"; import { OfficeSpace } from "../Corporation"; diff --git a/src/Corporation/ui/Overview.jsx b/src/Corporation/ui/Overview.jsx index 0c7c26d33..c33297e3c 100644 --- a/src/Corporation/ui/Overview.jsx +++ b/src/Corporation/ui/Overview.jsx @@ -158,7 +158,7 @@ export class Overview extends BaseReactComponent { onClick: findInvestorsOnClick, style: "inline-block", text: "Find Investors", - tooltip: findInvestorsTooltip + tooltip: findInvestorsTooltip, }); const goPublicBtn = this.createButton({ class: "std-button", @@ -167,7 +167,7 @@ export class Overview extends BaseReactComponent { text: "Go Public", tooltip: "Become a publicly traded and owned entity. Going public " + "involves issuing shares for an IPO. Once you are a public " + - "company, your shares will be traded on the stock market." + "company, your shares will be traded on the stock market.", }); return ( diff --git a/src/Corporation/ui/Routing.ts b/src/Corporation/ui/Routing.ts index 5e2c023fb..307f64f16 100644 --- a/src/Corporation/ui/Routing.ts +++ b/src/Corporation/ui/Routing.ts @@ -1,15 +1,27 @@ import { IMap } from "../../types"; -export const overviewPage: string = "Overview"; +export const overviewPage = "Overview"; // Interfaces for whatever's required to sanitize routing with Corporation Data interface IOfficeSpace { - + loc: string; + cost: number; + size: number; + comf: number; + beau: number; + tier: any; + minEne: number; + maxEne: number; + minHap: number; + maxHap: number; + maxMor: number; + employees: any; + employeeProd: any; } interface IDivision { name: string; - offices: IMap + offices: IMap; } interface ICorporation { @@ -76,7 +88,7 @@ export class CorporationRouting { for (let i = 0; i < this.corp.divisions.length; ++i) { if (this.corp.divisions[i].name === page) { this.currentDivision = this.corp.divisions[i]; - }; + } } // 'currentDivision' should not be null, since the routing is either on diff --git a/src/Crime/Crime.ts b/src/Crime/Crime.ts index 176069cf7..bbff32d4b 100644 --- a/src/Crime/Crime.ts +++ b/src/Crime/Crime.ts @@ -22,49 +22,49 @@ export interface IConstructorParams { export class Crime { // Number representing the difficulty of the crime. Used for success chance calculations - difficulty: number = 0; + difficulty = 0; // Amount of karma lost for SUCCESSFULLY committing this crime - karma: number = 0; + karma = 0; // How many people die as a result of this crime - kills: number = 0; + kills = 0; // How much money is given by the - money: number = 0; + money = 0; // Name of crime - name: string = ""; + name = ""; // Milliseconds it takes to attempt the crime - time: number = 0; + time = 0; // Corresponding type in CONSTANTS. Contains a description for the crime activity - type: string = ""; + type = ""; // Weighting factors that determine how stats affect the success rate of this crime - hacking_success_weight: number = 0; - strength_success_weight: number = 0; - defense_success_weight: number = 0; - dexterity_success_weight: number = 0; - agility_success_weight: number = 0; - charisma_success_weight: number = 0; + hacking_success_weight = 0; + strength_success_weight = 0; + defense_success_weight = 0; + dexterity_success_weight = 0; + agility_success_weight = 0; + charisma_success_weight = 0; // How much stat experience is granted by this crime - hacking_exp: number = 0; - strength_exp: number = 0; - defense_exp: number = 0; - dexterity_exp: number = 0; - agility_exp: number = 0; - charisma_exp: number = 0; - intelligence_exp: number = 0; + hacking_exp = 0; + strength_exp = 0; + defense_exp = 0; + dexterity_exp = 0; + agility_exp = 0; + charisma_exp = 0; + intelligence_exp = 0; - constructor(name: string = "", - type: string = "", - time: number = 0, - money: number = 0, - difficulty: number = 0, - karma: number = 0, + constructor(name = "", + type = "", + time = 0, + money = 0, + difficulty = 0, + karma = 0, params: IConstructorParams={}) { this.name = name; this.type = type; @@ -91,7 +91,7 @@ export class Crime { this.kills = params.kills ? params.kills : 0; } - commit(p: IPlayer, div: number=1, singParams: any=null): number { + commit(p: IPlayer, div=1, singParams: any=null): number { if (div <= 0) { div = 1; } p.startCrime( this.type, @@ -103,7 +103,7 @@ export class Crime { this.charisma_exp/div, this.money/div, this.time, - singParams + singParams, ); return this.time; diff --git a/src/Crime/CrimeHelpers.ts b/src/Crime/CrimeHelpers.ts index 27b2fd233..f617bb488 100644 --- a/src/Crime/CrimeHelpers.ts +++ b/src/Crime/CrimeHelpers.ts @@ -1,13 +1,14 @@ import { Crimes } from "./Crimes"; +import { Crime } from "./Crime"; import { IPlayer } from "../PersonObjects/IPlayer"; import { dialogBoxCreate } from "../../utils/DialogBox"; -export function determineCrimeSuccess(p: IPlayer, type: string) { - let chance: number = 0; - let found: boolean = false; +export function determineCrimeSuccess(p: IPlayer, type: string): boolean { + let chance = 0; + let found = false; for (const i in Crimes) { - let crime = Crimes[i]; + const crime = Crimes[i]; if (crime.type == type) { chance = crime.successRate(p); found = true; @@ -17,7 +18,7 @@ export function determineCrimeSuccess(p: IPlayer, type: string) { if (!found) { dialogBoxCreate(`ERR: Unrecognized crime type: ${type} This is probably a bug please contact the developer`, false); - return; + return false; } if (Math.random() <= chance) { @@ -29,7 +30,7 @@ export function determineCrimeSuccess(p: IPlayer, type: string) { } } -export function findCrime(roughName: string) { +export function findCrime(roughName: string): Crime | null { if (roughName.includes("shoplift")) { return Crimes.Shoplift; } else if (roughName.includes("rob") && roughName.includes("store")) { diff --git a/src/Crime/formulas/crime.ts b/src/Crime/formulas/crime.ts index 23748cfeb..c6cecb8a0 100644 --- a/src/Crime/formulas/crime.ts +++ b/src/Crime/formulas/crime.ts @@ -22,7 +22,7 @@ export interface IPerson { crime_success_mult: number; } -export function calculateCrimeSuccessChance(crime: ICrime, person: IPerson) { +export function calculateCrimeSuccessChance(crime: ICrime, person: IPerson): number { let chance: number = (crime.hacking_success_weight * person.hacking_skill + crime.strength_success_weight * person.strength + crime.defense_success_weight * person.defense + diff --git a/src/DarkWeb/DarkWeb.tsx b/src/DarkWeb/DarkWeb.tsx index b0cc18d98..380b91b83 100644 --- a/src/DarkWeb/DarkWeb.tsx +++ b/src/DarkWeb/DarkWeb.tsx @@ -7,8 +7,6 @@ import { post, postElement } from "../ui/postToTerminal"; import { Money } from "../ui/React/Money"; import { isValidIPAddress } from "../../utils/helpers/isValidIPAddress"; -import { formatNumber } from "../../utils/StringHelperFunctions"; -import { numeralWrapper } from "../ui/numeralFormat"; //Posts a "help" message if connected to DarkWeb export function checkIfConnectedToDarkweb(): void { @@ -29,27 +27,28 @@ export function checkIfConnectedToDarkweb(): void { export function executeDarkwebTerminalCommand(commandArray: string[]): void { if (commandArray.length == 0) {return;} switch (commandArray[0]) { - case "buy": + case "buy": { if (commandArray.length != 2) { post("Incorrect number of arguments. Usage: "); post("buy -l"); post("buy [item name]"); return; } - var arg = commandArray[1]; + const arg = commandArray[1]; if (arg == "-l") { listAllDarkwebItems(); } else { buyDarkwebItem(arg); } break; + } default: post("Command not found"); break; } } -function listAllDarkwebItems() { +function listAllDarkwebItems(): void { for(const key in DarkWebItems) { const item = DarkWebItems[key]; postElement(<>{item.program} - {Money(item.price)} - {item.description}); diff --git a/src/DarkWeb/DarkWebItem.ts b/src/DarkWeb/DarkWebItem.ts index 5045ee135..ce506a0eb 100644 --- a/src/DarkWeb/DarkWebItem.ts +++ b/src/DarkWeb/DarkWebItem.ts @@ -1,5 +1,3 @@ -import { numeralWrapper } from "../ui/numeralFormat"; - export class DarkWebItem { program: string; price: number; diff --git a/src/DevMenu.jsx b/src/DevMenu.jsx index b1c9167e7..fd19c44eb 100644 --- a/src/DevMenu.jsx +++ b/src/DevMenu.jsx @@ -3,10 +3,9 @@ import { CodingContractTypes } from "./CodingContracts"; import { generateContract, generateRandomContract, - generateRandomContractOnHome + generateRandomContractOnHome, } from "./CodingContractGenerator"; import { Companies } from "./Company/Companies"; -import { Company } from "./Company/Company"; import { Programs } from "./Programs/Programs"; import { Factions } from "./Faction/Factions"; import { Player } from "./Player"; @@ -14,17 +13,11 @@ import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile"; import { AllServers } from "./Server/AllServers"; import { GetServerByHostname } from "./Server/ServerHelpers"; import { hackWorldDaemon } from "./RedPill"; -import { StockMarket, SymbolToStockMap } from "./StockMarket/StockMarket"; +import { StockMarket } from "./StockMarket/StockMarket"; import { Stock } from "./StockMarket/Stock"; -import { Terminal } from "./Terminal"; - -import { numeralWrapper } from "./ui/numeralFormat"; import { dialogBoxCreate } from "../utils/DialogBox"; -import { exceptionAlert } from "../utils/helpers/exceptionAlert"; import { createElement } from "../utils/uiHelpers/createElement"; -import { createOptionElement } from "../utils/uiHelpers/createOptionElement"; -import { getSelectText } from "../utils/uiHelpers/getSelectData"; import { removeElementById } from "../utils/uiHelpers/removeElementById"; import { Money } from "./ui/React/Money"; @@ -47,12 +40,13 @@ class ValueAdjusterComponent extends Component { this.state = { value: '' }; this.setValue = this.setValue.bind(this); } + setValue(event) { this.setState({ value: parseFloat(event.target.value) }); } + render() { const { title, add, subtract, reset } = this.props; - const { value } = this.state; return ( <> @@ -141,6 +135,10 @@ class DevMenuComponent extends Component { Player.getHomeComputer().maxRam *= 2; } + quickB1tFlum3() { + hackWorldDaemon(Player.bitNodeN, true, true); + } + b1tflum3() { hackWorldDaemon(Player.bitNodeN, true); } @@ -279,9 +277,8 @@ class DevMenuComponent extends Component { } modifyFactionRep(modifier) { - const component = this; - return function(reputation) { - const fac = Factions[component.state.faction]; + return (reputation) => { + const fac = Factions[this.state.faction]; if (fac != null && !isNaN(reputation)) { fac.playerReputation += reputation*modifier; } @@ -296,9 +293,8 @@ class DevMenuComponent extends Component { } modifyFactionFavor(modifier) { - const component = this; - return function(favor) { - const fac = Factions[component.state.faction]; + return (favor) => { + const fac = Factions[this.state.faction]; if (fac != null && !isNaN(favor)) { fac.favor += favor*modifier; } @@ -368,10 +364,9 @@ class DevMenuComponent extends Component { } setAllSF(sfLvl) { - const component = this; - return function(){ + return () => { for (let i = 0; i < validSFN.length; i++) { - component.setSF(validSFN[i], sfLvl)(); + this.setSF(validSFN[i], sfLvl)(); } } } @@ -441,9 +436,8 @@ class DevMenuComponent extends Component { } modifyCompanyRep(modifier) { - const component = this; - return function(reputation) { - const company = Companies[component.state.company]; + return (reputation) => { + const company = Companies[this.state.company]; if (company != null && !isNaN(reputation)) { company.playerReputation += reputation*modifier; } @@ -456,9 +450,8 @@ class DevMenuComponent extends Component { } modifyCompanyFavor(modifier) { - const component = this; - return function(favor) { - const company = Companies[component.state.company]; + return (favor) => { + const company = Companies[this.state.company]; if (company != null && !isNaN(favor)) { company.favor += favor*modifier; } @@ -496,7 +489,7 @@ class DevMenuComponent extends Component { modifyBladeburnerRank(modify) { return function(rank) { - if (!!Player.bladeburner) { + if (Player.bladeburner) { Player.bladeburner.changeRank(rank*modify); } } @@ -508,67 +501,67 @@ class DevMenuComponent extends Component { } addTonsBladeburnerRank() { - if (!!Player.bladeburner) { + if (Player.bladeburner) { Player.bladeburner.changeRank(tonsP); } } modifyBladeburnerCycles(modify) { return function(cycles) { - if (!!Player.bladeburner) { + if (Player.bladeburner) { Player.bladeburner.storedCycles += cycles*modify; } } } resetBladeburnerCycles() { - if (!!Player.bladeburner) { + if (Player.bladeburner) { Player.bladeburner.storedCycles = 0; } } addTonsBladeburnerCycles() { - if (!!Player.bladeburner) { + if (Player.bladeburner) { Player.bladeburner.storedCycles += tonsP; } } addTonsGangCycles() { - if (!!Player.gang) { + if (Player.gang) { Player.gang.storedCycles = tonsP; } } modifyGangCycles(modify) { return function(cycles) { - if (!!Player.gang) { + if (Player.gang) { Player.gang.storedCycles += cycles*modify; } } } resetGangCycles() { - if (!!Player.gang) { + if (Player.gang) { Player.gang.storedCycles = 0; } } addTonsCorporationCycles() { - if (!!Player.corporation) { + if (Player.corporation) { Player.corporation.storedCycles = tonsP; } } modifyCorporationCycles(modify) { return function(cycles) { - if (!!Player.corporation) { + if (Player.corporation) { Player.corporation.storedCycles += cycles*modify; } } } resetCorporationCycles() { - if (!!Player.corporation) { + if (Player.corporation) { Player.corporation.storedCycles = 0; } } @@ -580,10 +573,10 @@ class DevMenuComponent extends Component { }); } - processStocks(cb) { + processStocks(sub) { const inputSymbols = document.getElementById('dev-stock-symbol').value.toString().replace(/\s/g, ''); - let match = function(symbol) { return true; } + let match = function() { return true; } if (inputSymbols !== '' && inputSymbols !== 'all') { match = function(symbol) { @@ -595,7 +588,7 @@ class DevMenuComponent extends Component { if (StockMarket.hasOwnProperty(name)) { const stock = StockMarket[name]; if (stock instanceof Stock && match(stock.symbol)) { - cb(stock); + sub(stock); } } } @@ -636,13 +629,13 @@ class DevMenuComponent extends Component { } } - sleeveMaxAllSync() { + sleeveSyncMaxAll() { for (let i = 0; i < Player.sleeves.length; ++i) { Player.sleeves[i].sync = 100; } } - sleeveClearAllSync() { + sleeveSyncClearAll() { for (let i = 0; i < Player.sleeves.length; ++i) { Player.sleeves[i].sync = 0; } @@ -674,7 +667,7 @@ class DevMenuComponent extends Component { - + , )); @@ -716,7 +709,8 @@ class DevMenuComponent extends Component {
    - + +
    @@ -1210,8 +1204,8 @@ class DevMenuComponent extends Component {
    - - + +
    Sync:
    diff --git a/src/Exploits/applyExploits.ts b/src/Exploits/applyExploits.ts index c2671b025..fede837a4 100644 --- a/src/Exploits/applyExploits.ts +++ b/src/Exploits/applyExploits.ts @@ -1,11 +1,11 @@ import { Player } from "../Player"; -export function applyExploit() { +export function applyExploit(): void { if (Player.exploits && Player.exploits.length === 0) { return; } - const inc = Math.pow(1.0001, Player.exploits.length); - const dec = Math.pow(0.9999, Player.exploits.length); + const inc = Math.pow(1.001, Player.exploits.length); + const dec = Math.pow(0.999, Player.exploits.length); Player.hacking_chance_mult *= inc; Player.hacking_speed_mult *= inc; diff --git a/src/Exploits/unclickable.ts b/src/Exploits/unclickable.ts index 0ee7cd696..97cdbc214 100644 --- a/src/Exploits/unclickable.ts +++ b/src/Exploits/unclickable.ts @@ -2,7 +2,7 @@ import { Player } from "../Player"; import { Exploit } from "./Exploit"; (function() { - function clickTheUnclickable(event: MouseEvent) { + function clickTheUnclickable(event: MouseEvent): void { if(!event.target || !(event.target instanceof Element)) return; const display = window.getComputedStyle(event.target as Element).display; if(display === 'none' && event.isTrusted) @@ -10,7 +10,7 @@ import { Exploit } from "./Exploit"; } - function targetElement() { + function targetElement(): void { const elem = document.getElementById('unclickable'); if(elem == null) { console.error('Could not find the unclickable elem for the related exploit.'); diff --git a/src/Faction/Faction.ts b/src/Faction/Faction.ts index 2bf4b372e..233ae0dcc 100644 --- a/src/Faction/Faction.ts +++ b/src/Faction/Faction.ts @@ -4,18 +4,12 @@ import { FactionInfo, import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; export class Faction { - /** - * Initiatizes a Faction object from a JSON save state. - */ - static fromJSON(value: any): Faction { - return Generic_fromJSON(Faction, value.data); - } /** * Flag signalling whether the player has already received an invitation * to this faction */ - alreadyInvited: boolean = false; + alreadyInvited = false; /** * Holds names of all augmentations that this Faction offers @@ -25,35 +19,35 @@ export class Faction { /** * Amount of favor the player has with this faction. */ - favor: number = 0; + favor = 0; /** * Flag signalling whether player has been banned from this faction */ - isBanned: boolean = false; + isBanned = false; /** * Flag signalling whether player is a member of this faction */ - isMember: boolean = false; + isMember = false; /** * Name of faction */ - name: string = ""; + name = ""; /** * Amount of reputation player has with this faction */ - playerReputation: number = 0; + playerReputation = 0; /** * Reputation from the last "prestige" that was not converted to favor. * This reputation rolls over and is used for the next favor calculation */ - rolloverRep: number = 0; + rolloverRep = 0; - constructor(name: string="") { + constructor(name="") { this.name = name; } @@ -82,7 +76,7 @@ export class Faction { getFavorGain(): number[] { if (this.favor == null) { this.favor = 0; } if (this.rolloverRep == null) { this.rolloverRep = 0; } - var favorGain = 0, rep = this.playerReputation + this.rolloverRep; + let favorGain = 0, rep = this.playerReputation + this.rolloverRep; let reqdRep = CONSTANTS.FactionReputationToFavorBase * Math.pow(CONSTANTS.FactionReputationToFavorMult, this.favor); while(rep > 0) { @@ -103,6 +97,14 @@ export class Faction { toJSON(): any { return Generic_toJSON("Faction", this); } + + /** + * Initiatizes a Faction object from a JSON save state. + */ + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + static fromJSON(value: any): Faction { + return Generic_fromJSON(Faction, value.data); + } } Reviver.constructors.Faction = Faction; diff --git a/src/Faction/FactionHelpers.jsx b/src/Faction/FactionHelpers.jsx index 0926b2faf..b9fb9e8dc 100644 --- a/src/Faction/FactionHelpers.jsx +++ b/src/Faction/FactionHelpers.jsx @@ -24,19 +24,12 @@ import { import { Page, routing } from "../ui/navigationTracking"; import { dialogBoxCreate } from "../../utils/DialogBox"; import { factionInvitationBoxCreate } from "../../utils/FactionInvitationBox"; -import { - Reviver, - Generic_toJSON, - Generic_fromJSON -} from "../../utils/JSONReviver"; -import { formatNumber } from "../../utils/StringHelperFunctions"; -import { numeralWrapper } from "../ui/numeralFormat"; import { Money } from "../ui/React/Money"; import { yesNoBoxCreate, yesNoBoxGetYesButton, yesNoBoxGetNoButton, - yesNoBoxClose + yesNoBoxClose, } from "../../utils/YesNoBox"; export function inviteToFaction(faction) { @@ -90,7 +83,7 @@ export function displayFactionContent(factionName, initiallyOnAugmentationsPage= p={Player} startHackingMissionFn={startHackingMission} />, - Engine.Display.factionContent + Engine.Display.factionContent, ) } diff --git a/src/Faction/Factions.ts b/src/Faction/Factions.ts index a5c05e809..8616018f0 100644 --- a/src/Faction/Factions.ts +++ b/src/Faction/Factions.ts @@ -16,7 +16,7 @@ export function loadFactions(saveString: string): void { Factions = JSON.parse(saveString, Reviver); } -export function AddToFactions(faction: Faction) { +export function AddToFactions(faction: Faction): void { const name: string = faction.name; Factions[name] = faction; } @@ -25,7 +25,7 @@ export function factionExists(name: string): boolean { return Factions.hasOwnProperty(name); } -export function initFactions(bitNode: number=1) { +export function initFactions(): void { for (const name in FactionInfos) { resetFaction(new Faction(name)); } @@ -34,7 +34,7 @@ export function initFactions(bitNode: number=1) { //Resets a faction during (re-)initialization. Saves the favor in the new //Faction object and deletes the old Faction Object from "Factions". Then //reinserts the new Faction object -export function resetFaction(newFactionObject: Faction) { +export function resetFaction(newFactionObject: Faction): void { if (!(newFactionObject instanceof Faction)) { throw new Error("Invalid argument 'newFactionObject' passed into resetFaction()"); } diff --git a/src/Faction/ui/AugmentationsPage.tsx b/src/Faction/ui/AugmentationsPage.tsx index c950c8291..5ac4ee8b5 100644 --- a/src/Faction/ui/AugmentationsPage.tsx +++ b/src/Faction/ui/AugmentationsPage.tsx @@ -77,7 +77,7 @@ export class AugmentationsPage extends React.Component { getAugsSortedByCost(): string[] { const augs = this.getAugs(); augs.sort((augName1, augName2)=>{ - var aug1 = Augmentations[augName1], aug2 = Augmentations[augName2]; + const aug1 = Augmentations[augName1], aug2 = Augmentations[augName2]; if (aug1 == null || aug2 == null) { throw new Error("Invalid Augmentation Names"); } @@ -91,7 +91,7 @@ export class AugmentationsPage extends React.Component { getAugsSortedByReputation(): string[] { const augs = this.getAugs(); augs.sort((augName1, augName2)=>{ - var aug1 = Augmentations[augName1], aug2 = Augmentations[augName2]; + const aug1 = Augmentations[augName1], aug2 = Augmentations[augName2]; if (aug1 == null || aug2 == null) { throw new Error("Invalid Augmentation Names"); } @@ -118,23 +118,21 @@ export class AugmentationsPage extends React.Component { }); } - render() { + render(): React.ReactNode { const augs = this.getAugsSorted(); - const purchasable = augs.filter((aug: string) => - aug === AugmentationNames.NeuroFluxGovernor || + const purchasable = augs.filter((aug: string) => aug === AugmentationNames.NeuroFluxGovernor || (!this.props.p.augmentations.some(a => a.name === aug) && - !this.props.p.queuedAugmentations.some(a => a.name === aug)) + !this.props.p.queuedAugmentations.some(a => a.name === aug)), ) - const parent = this; - function purchaseableAugmentation(aug: string) { + const purchaseableAugmentation = (aug: string): React.ReactNode => { return ( ) } diff --git a/src/Faction/ui/DonateOption.tsx b/src/Faction/ui/DonateOption.tsx index acb2e9222..c7bed8247 100644 --- a/src/Faction/ui/DonateOption.tsx +++ b/src/Faction/ui/DonateOption.tsx @@ -7,7 +7,6 @@ import { CONSTANTS } from "../../Constants"; import { Faction } from "../../Faction/Faction"; import { IPlayer } from "../../PersonObjects/IPlayer"; -import { numeralWrapper } from "../../ui/numeralFormat"; import { Money } from "../../ui/React/Money"; import { Reputation } from "../../ui/React/Reputation"; @@ -17,6 +16,8 @@ import { dialogBoxCreate } from "../../../utils/DialogBox"; type IProps = { faction: Faction; + disabled: boolean; + favorToDonate: number; p: IPlayer; rerender: () => void; } @@ -32,14 +33,15 @@ const inputStyleMarkup = { export class DonateOption extends React.Component { // Style markup for block elements. Stored as property - blockStyle: object = { display: "block" }; + blockStyle: any = { display: "block" }; constructor(props: IProps) { super(props); + this.state = { donateAmt: 0, - status: <>, + status: props.disabled ? <>Unlocked at {props.favorToDonate} favor with {props.faction.name} : <>, } this.calculateRepGain = this.calculateRepGain.bind(this); @@ -87,14 +89,21 @@ export class DonateOption extends React.Component { } } - render() { + render(): React.ReactNode { return (
    - +

    {this.state.status}

    diff --git a/src/Faction/ui/Info.tsx b/src/Faction/ui/Info.tsx index 4990f1aa5..22aa7c553 100644 --- a/src/Faction/ui/Info.tsx +++ b/src/Faction/ui/Info.tsx @@ -6,7 +6,6 @@ import * as React from "react"; import { Faction } from "../../Faction/Faction"; import { FactionInfo } from "../../Faction/FactionInfo"; -import { numeralWrapper } from "../../ui/numeralFormat"; import { AutoupdatingParagraph } from "../../ui/React/AutoupdatingParagraph"; import { ParagraphWithTooltip } from "../../ui/React/ParagraphWithTooltip"; @@ -48,7 +47,7 @@ export class Info extends React.Component { return <>Reputation: {Reputation(this.props.faction.playerReputation)} } - render() { + render(): React.ReactNode { const favorTooltip = "Faction favor increases the rate at which you earn reputation for " + "this faction by 1% per favor. Faction favor is gained whenever you " + "reset after installing an Augmentation. The amount of " + diff --git a/src/Faction/ui/Option.tsx b/src/Faction/ui/Option.tsx index 72c96df36..148790886 100644 --- a/src/Faction/ui/Option.tsx +++ b/src/Faction/ui/Option.tsx @@ -14,7 +14,7 @@ type IProps = { } export class Option extends React.Component { - render() { + render(): React.ReactNode { return (
    diff --git a/src/Faction/ui/PurchaseableAugmentation.tsx b/src/Faction/ui/PurchaseableAugmentation.tsx index 95f53bddd..ece801260 100644 --- a/src/Faction/ui/PurchaseableAugmentation.tsx +++ b/src/Faction/ui/PurchaseableAugmentation.tsx @@ -17,7 +17,6 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; import { Faction } from "../../Faction/Faction"; import { IPlayer } from "../../PersonObjects/IPlayer"; import { Settings } from "../../Settings/Settings"; -import { numeralWrapper } from "../../ui/numeralFormat"; import { Money } from "../../ui/React/Money"; import { Reputation } from "../../ui/React/Reputation"; import { IMap } from "../../types"; @@ -42,35 +41,37 @@ const inlineStyleMarkup = { } export class PurchaseableAugmentation extends React.Component { - aug: Augmentation | null; + aug: Augmentation; constructor(props: IProps) { super(props); - this.aug = Augmentations[this.props.augName]; + const aug = Augmentations[this.props.augName]; + if(aug == null) throw new Error(`aug ${this.props.augName} does not exists`); + this.aug = aug; this.handleClick = this.handleClick.bind(this); } getMoneyCost(): number { - return this.aug!.baseCost * this.props.faction.getInfo().augmentationPriceMult; + return this.aug.baseCost * this.props.faction.getInfo().augmentationPriceMult; } getRepCost(): number { - return this.aug!.baseRepRequirement * this.props.faction.getInfo().augmentationRepRequirementMult; + return this.aug.baseRepRequirement * this.props.faction.getInfo().augmentationRepRequirementMult; } - handleClick() { + handleClick(): void { if (!Settings.SuppressBuyAugmentationConfirmation) { - purchaseAugmentationBoxCreate(this.aug!, this.props.faction); + purchaseAugmentationBoxCreate(this.aug, this.props.faction); } else { - purchaseAugmentation(this.aug!, this.props.faction); + purchaseAugmentation(this.aug, this.props.faction); } } // Whether the player has the prerequisite Augmentations hasPrereqs(): boolean { - return hasAugmentationPrereqs(this.aug!); + return hasAugmentationPrereqs(this.aug); } // Whether the player has enough rep for this Augmentation @@ -98,7 +99,7 @@ export class PurchaseableAugmentation extends React.Component { return owned; } - render() { + render(): React.ReactNode { if (this.aug == null) { console.error(`Invalid Augmentation when trying to create PurchaseableAugmentation display element: ${this.props.augName}`); return null; @@ -108,9 +109,9 @@ export class PurchaseableAugmentation extends React.Component { const repCost = this.getRepCost(); // Determine UI properties - let disabled: boolean = false; + let disabled = false; let status: JSX.Element = <>; - let color: string = ""; + let color = ""; if (!this.hasPrereqs()) { disabled = true; status = <>LOCKED (Requires {this.aug.prereqs.map(aug => AugFormat(aug))} as prerequisite); diff --git a/src/Faction/ui/Root.tsx b/src/Faction/ui/Root.tsx index aa0c2a935..5e8259436 100644 --- a/src/Faction/ui/Root.tsx +++ b/src/Faction/ui/Root.tsx @@ -69,7 +69,7 @@ const GangNames = [ "The Dark Army", "Speakers for the Dead", "NiteSec", - "The Black Hand" + "The Black Hand", ]; export class FactionRoot extends React.Component { @@ -92,7 +92,7 @@ export class FactionRoot extends React.Component { this.startSecurityWork = this.startSecurityWork.bind(this); } - manageGang() { + manageGang(): void { // If player already has a gang, just go to the gang UI if (this.props.p.inGang()) { return this.props.engine.loadGangContent(); @@ -146,7 +146,7 @@ export class FactionRoot extends React.Component { "create a Gang with, and each of these Factions have all Augmentations available."); } - rerender() { + rerender(): void { this.setState((prevState) => { return { rerenderFlag: !prevState.rerenderFlag, @@ -155,42 +155,42 @@ export class FactionRoot extends React.Component { } // Route to the main faction page - routeToMain() { + routeToMain(): void { this.setState({ purchasingAugs: false }); } // Route to the purchase augmentation UI for this faction - routeToPurchaseAugs() { + routeToPurchaseAugs(): void { this.setState({ purchasingAugs: true }); } - sleevePurchases() { + sleevePurchases(): void { createSleevePurchasesFromCovenantPopup(this.props.p); } - startFieldWork() { + startFieldWork(): void { this.props.p.startFactionFieldWork(this.props.faction); } - startHackingContracts() { + startHackingContracts(): void { this.props.p.startFactionHackWork(this.props.faction); } - startHackingMission() { + startHackingMission(): void { const fac = this.props.faction; this.props.engine.loadMissionContent(); this.props.startHackingMissionFn(fac); } - startSecurityWork() { + startSecurityWork(): void { this.props.p.startFactionSecurityWork(this.props.faction); } - render() { + render(): React.ReactNode { return this.state.purchasingAugs ? this.renderAugmentationsPage() : this.renderMainPage(); } - renderMainPage() { + renderMainPage(): React.ReactNode { const p = this.props.p; const faction = this.props.faction; const factionInfo = faction.getInfo(); @@ -264,11 +264,13 @@ export class FactionRoot extends React.Component { /> } { - (!isPlayersGang && canDonate) && + !isPlayersGang && }
    + ) } } \ No newline at end of file diff --git a/src/ui/React/CopyableText.tsx b/src/ui/React/CopyableText.tsx index da103505b..26ea3dc1a 100644 --- a/src/ui/React/CopyableText.tsx +++ b/src/ui/React/CopyableText.tsx @@ -21,7 +21,7 @@ export class CopyableText extends React.Component { } } - copy(e: React.MouseEvent) { + copy(): void { const copyText = document.createElement("textarea"); copyText.value = this.props.value; document.body.appendChild(copyText); @@ -52,7 +52,7 @@ export class CopyableText extends React.Component { } - render() { + render(): React.ReactNode { return ( {this.props.value} Copied! diff --git a/src/ui/React/CorruptableText.tsx b/src/ui/React/CorruptableText.tsx index 4a54e0175..926e1ece6 100644 --- a/src/ui/React/CorruptableText.tsx +++ b/src/ui/React/CorruptableText.tsx @@ -26,7 +26,7 @@ function randomize(char: string): string { return randFrom(other); } -export function CorruptableText(props: IProps) { +export function CorruptableText(props: IProps): JSX.Element { const [content, setContent] = useState(props.content); useEffect(() => { diff --git a/src/ui/React/ErrorBoundary.tsx b/src/ui/React/ErrorBoundary.tsx index 203f0c5fe..ee65679b8 100644 --- a/src/ui/React/ErrorBoundary.tsx +++ b/src/ui/React/ErrorBoundary.tsx @@ -37,45 +37,40 @@ export class ErrorBoundary extends React.Component { } } - static getDerivedStateFromError(error: Error) { - return { - errorInfo: error.message, - hasError: true, - }; - } - - componentDidCatch(error: Error, info: IErrorInfo) { + componentDidCatch(error: Error, info: IErrorInfo): void { console.error(`Caught error in React ErrorBoundary. Component stack:`); console.error(info.componentStack); } - componentDidMount() { - const cb = () => { + componentDidMount(): void { + const cb = (): void => { this.setState({ hasError: false, }); } if (this.hasEventEmitter()) { - this.props.eventEmitterForReset!.addSubscriber({ + (this.props.eventEmitterForReset as EventEmitter).addSubscriber({ cb: cb, - id: this.props.id!, + id: (this.props.id as string), }); } } - componentWillUnmount() { + componentWillUnmount(): void { if (this.hasEventEmitter()) { - this.props.eventEmitterForReset!.removeSubscriber(this.props.id!); + (this.props.eventEmitterForReset as EventEmitter).removeSubscriber((this.props.id as string)); } } hasEventEmitter(): boolean { - return this.props.eventEmitterForReset instanceof EventEmitter - && typeof this.props.id === "string"; + return this.props.eventEmitterForReset != null && + this.props.eventEmitterForReset instanceof EventEmitter && + this.props.id != null && + typeof this.props.id === "string"; } - render() { + render(): React.ReactNode { if (this.state.hasError) { return (
    @@ -100,4 +95,11 @@ export class ErrorBoundary extends React.Component { return this.props.children; } + + static getDerivedStateFromError(error: Error): IState { + return { + errorInfo: error.message, + hasError: true, + }; + } } diff --git a/src/ui/React/HashRate.tsx b/src/ui/React/HashRate.tsx index c19759c0d..88785f3dc 100644 --- a/src/ui/React/HashRate.tsx +++ b/src/ui/React/HashRate.tsx @@ -1,4 +1,3 @@ -import * as React from "react"; import { numeralWrapper } from "../../ui/numeralFormat"; import { Hashes } from "../../ui/React/Hashes"; diff --git a/src/ui/React/MoneyRate.tsx b/src/ui/React/MoneyRate.tsx index e0b832675..6e03a06f5 100644 --- a/src/ui/React/MoneyRate.tsx +++ b/src/ui/React/MoneyRate.tsx @@ -1,4 +1,3 @@ -import * as React from "react"; import { numeralWrapper } from "../../ui/numeralFormat"; import { Money } from "../../ui/React/Money"; diff --git a/src/ui/React/ParagraphWithTooltip.tsx b/src/ui/React/ParagraphWithTooltip.tsx index fb2af3933..288b53fee 100644 --- a/src/ui/React/ParagraphWithTooltip.tsx +++ b/src/ui/React/ParagraphWithTooltip.tsx @@ -4,13 +4,13 @@ import * as React from "react"; export interface IParagraphWithTooltipProps { - style?: object; + style?: any; content: JSX.Element; tooltip: string; } export class ParagraphWithTooltip extends React.Component { - render() { + render(): React.ReactNode { return (

    {this.props.content} diff --git a/src/ui/React/Popup.tsx b/src/ui/React/Popup.tsx index c296809bb..89f2a3c12 100644 --- a/src/ui/React/Popup.tsx +++ b/src/ui/React/Popup.tsx @@ -10,7 +10,7 @@ type ReactComponent = new(...args: any[]) => React.Component interface IProps { content: ReactComponent; id: string; - props: object; + props: any; } export function Popup(props: IProps): React.ReactElement { diff --git a/src/ui/React/PopupCloseButton.tsx b/src/ui/React/PopupCloseButton.tsx index dfd581926..8375fabec 100644 --- a/src/ui/React/PopupCloseButton.tsx +++ b/src/ui/React/PopupCloseButton.tsx @@ -14,7 +14,7 @@ import { removeElement } from "../../../utils/uiHelpers/removeElement"; export interface IPopupCloseButtonProps { class?: string; popup: HTMLElement | string; - style?: object; + style?: any; text: string; } @@ -26,15 +26,15 @@ export class PopupCloseButton extends React.Component) => any; - style?: object; + style?: any; text: string | JSX.Element; tooltip?: string | JSX.Element; } @@ -33,13 +33,12 @@ export function StdButton(props: IStdButtonProps): React.ReactElement { let tooltip; if (hasTooltip) { if(typeof props.tooltip === 'string') { - let tooltipMarkup: IInnerHTMLMarkup | null; - tooltipMarkup = { - __html: props.tooltip! + const tooltipMarkup: IInnerHTMLMarkup = { + __html: props.tooltip, } - tooltip = + tooltip = } else { - tooltip = {props.tooltip!} + tooltip = {props.tooltip} } } diff --git a/src/ui/React/StdButtonPurchased.tsx b/src/ui/React/StdButtonPurchased.tsx index db041af0a..afdab4cba 100644 --- a/src/ui/React/StdButtonPurchased.tsx +++ b/src/ui/React/StdButtonPurchased.tsx @@ -5,7 +5,7 @@ import * as React from "react"; interface IStdButtonPurchasedProps { onClick?: (e: React.MouseEvent) => any; - style?: object; + style?: any; text: string; tooltip?: string; } @@ -15,18 +15,35 @@ type IInnerHTMLMarkup = { } export class StdButtonPurchased extends React.Component { - render() { - const hasTooltip = this.props.tooltip != null && this.props.tooltip !== ""; + + constructor(props: IStdButtonPurchasedProps) { + super(props); + this.hasTooltip = this.hasTooltip.bind(this); + this.tooltip = this.tooltip.bind(this); + } + + hasTooltip(): boolean { + return this.props.tooltip != null && this.props.tooltip !== ""; + } + + tooltip(): string { + if(!this.props.tooltip) return ""; + return this.props.tooltip; + } + + render(): React.ReactNode { let className = "std-button-bought"; - if (hasTooltip) { + if (this.hasTooltip()) { className += " tooltip"; } // Tooltip will be set using inner HTML - let tooltipMarkup: IInnerHTMLMarkup | null; - if (hasTooltip) { + let tooltipMarkup: IInnerHTMLMarkup = { + __html: "", + } + if (this.hasTooltip()) { tooltipMarkup = { - __html: this.props.tooltip! + __html: this.tooltip(), } } @@ -34,8 +51,8 @@ export class StdButtonPurchased extends React.Component {this.props.text} { - hasTooltip && - + this.hasTooltip() && + } ) diff --git a/src/ui/React/createPopup.tsx b/src/ui/React/createPopup.tsx index 3f9bb5e25..0f1a7d4a3 100644 --- a/src/ui/React/createPopup.tsx +++ b/src/ui/React/createPopup.tsx @@ -18,8 +18,8 @@ type ReactComponent = new(...args: any[]) => React.Component; let gameContainer: HTMLElement; -function getGameContainer() { - let container = document.getElementById("entire-game-container"); +function getGameContainer(): void { + const container = document.getElementById("entire-game-container"); if (container == null) { throw new Error(`Failed to find game container DOM element`) } @@ -30,7 +30,8 @@ function getGameContainer() { document.addEventListener("DOMContentLoaded", getGameContainer); -export function createPopup(id: string, rootComponent: ReactComponent, props: object): HTMLElement | null { +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export function createPopup(id: string, rootComponent: ReactComponent, props: any): HTMLElement | null { let container = document.getElementById(id); if (container == null) { container = createElement("div", { @@ -51,7 +52,7 @@ export function createPopup(id: string, rootComponent: ReactComponent, props: ob * Closes a popup created with the createPopup() function above */ export function removePopup(id: string): void { - let content = document.getElementById(`${id}`); + const content = document.getElementById(`${id}`); if (content == null) { return; } ReactDOM.unmountComponentAtNode(content); diff --git a/src/ui/createStatusText.ts b/src/ui/createStatusText.ts index 161eb047e..58ee30947 100644 --- a/src/ui/createStatusText.ts +++ b/src/ui/createStatusText.ts @@ -2,14 +2,14 @@ import { setTimeoutRef } from "../utils/SetTimeoutRef"; import { getElementById } from "../../utils/uiHelpers/getElementById"; import { Action } from "../types"; -const threeSeconds: number = 3000; +const threeSeconds = 3000; let x: number | undefined; /** * Displays a status message to the player for approximately 3 seconds. * @param text The status text to display */ -export function createStatusText(text: string) { +export function createStatusText(text: string): void { if (x !== undefined) { clearTimeout(x); // Likely not needed due to clearTimeout, but just in case... diff --git a/src/ui/navigationTracking.ts b/src/ui/navigationTracking.ts index 7f448aed4..6005c7b56 100644 --- a/src/ui/navigationTracking.ts +++ b/src/ui/navigationTracking.ts @@ -137,7 +137,7 @@ class Routing { * Determines if the player is currently on the specified page. * @param page The page to compare against the current state. */ - isOn(page: Page) { + isOn(page: Page): boolean { return this.currentPage === page; } @@ -145,7 +145,7 @@ class Routing { * Routes the player to the appropriate page. * @param page The page to navigate to. */ - navigateTo(page: Page) { + navigateTo(page: Page): void { this.currentPage = page; } } diff --git a/src/ui/numeralFormat.ts b/src/ui/numeralFormat.ts index 3c4e7c5f9..30d55cf3c 100644 --- a/src/ui/numeralFormat.ts +++ b/src/ui/numeralFormat.ts @@ -53,6 +53,9 @@ class NumeralFormatter { } formatMoney(n: number): string { + if(n < 1000) { + return this.format(n, "$0.00"); + } return this.format(n, "$0.000a"); } @@ -85,7 +88,7 @@ class NumeralFormatter { return this.format(n, formatter); } - formatServerSecurity(n: number, decimalPlaces = 2): string { + formatServerSecurity(n: number): string { return this.format(n, "0,0.000"); } @@ -101,15 +104,15 @@ class NumeralFormatter { return this.format(n, "0,0.00"); } - formatShock(n: number): string { + formatSleeveShock(n: number): string { return this.format(n, "0,0.000"); } - formatSync(n: number): string { + formatSleeveSynchro(n: number): string { return this.format(n, "0,0.000"); } - formatMemory(n: number): string { + formatSleeveMemory(n: number): string { return this.format(n, "0"); } @@ -131,6 +134,10 @@ class NumeralFormatter { formatInfiltrationSecurity(n: number): string { return this.format(n, "0.000a"); } + + formatThreads(n: number): string { + return this.format(n, "0,0"); + } } export const numeralWrapper = new NumeralFormatter(); diff --git a/src/ui/postToTerminal.tsx b/src/ui/postToTerminal.tsx index 5716e8569..7f06e03ff 100644 --- a/src/ui/postToTerminal.tsx +++ b/src/ui/postToTerminal.tsx @@ -1,4 +1,3 @@ -import * as React from "react"; import { renderToStaticMarkup } from "react-dom/server" import { getElementById } from "../../utils/uiHelpers/getElementById"; @@ -6,11 +5,11 @@ import { getElementById } from "../../utils/uiHelpers/getElementById"; * Adds some output to the terminal. * @param input Text or HTML to output to the terminal */ -export function post(input: string) { +export function post(input: string): void { postContent(input); } -export function postError(input: string) { +export function postError(input: string): void { postContent(`ERROR: ${input}`, { color: "#ff2929" }); } @@ -18,7 +17,7 @@ export function postError(input: string) { * Adds some output to the terminal with an identifier of "hack-progress-bar" * @param input Text or HTML to output to the terminal */ -export function hackProgressBarPost(input: string) { +export function hackProgressBarPost(input: string): void { postContent(input, { id: "hack-progress-bar" }); } @@ -26,7 +25,7 @@ export function hackProgressBarPost(input: string) { * Adds some output to the terminal with an identifier of "hack-progress" * @param input Text or HTML to output to the terminal */ -export function hackProgressPost(input: string) { +export function hackProgressPost(input: string): void { postContent(input, { id: "hack-progress" }); } @@ -35,21 +34,21 @@ interface IPostContentConfig { color?: string; // Additional class for terminal-line. Does NOT replace } -export function postElement(element: JSX.Element) { +export function postElement(element: JSX.Element): void { postContent(renderToStaticMarkup(element)); } -export function postContent(input: string, config: IPostContentConfig = {}) { +export function postContent(input: string, config: IPostContentConfig = {}): void { // tslint:disable-next-line:max-line-length - const style: string = `color: ${config.color != null ? config.color : "var(--my-font-color)"}; background-color:var(--my-background-color);${config.id === undefined ? " white-space:pre-wrap;" : ""}`; + const style = `color: ${config.color != null ? config.color : "var(--my-font-color)"}; background-color:var(--my-background-color);${config.id === undefined ? " white-space:pre-wrap;" : ""}`; // tslint:disable-next-line:max-line-length - const content: string = `${input}`; + const content = `${input}`; const inputElement: HTMLElement = getElementById("terminal-input"); inputElement.insertAdjacentHTML("beforebegin", content); scrollTerminalToBottom(); } -function scrollTerminalToBottom() { +function scrollTerminalToBottom(): void { const container: HTMLElement = getElementById("terminal-container"); container.scrollTop = container.scrollHeight; } diff --git a/src/utils/EventEmitter.ts b/src/utils/EventEmitter.ts index b513d76d5..5064ac05f 100644 --- a/src/utils/EventEmitter.ts +++ b/src/utils/EventEmitter.ts @@ -31,19 +31,19 @@ export class EventEmitter { } } - addSubscriber(s: ISubscriber) { + addSubscriber(s: ISubscriber): void { this.subscribers[s.id] = s.cb; } emitEvent(...args: any[]): void { for (const s in this.subscribers) { - const cb = this.subscribers[s]; + const sub = this.subscribers[s]; - cb(args); + sub(args); } } - removeSubscriber(id: string) { + removeSubscriber(id: string): void { delete this.subscribers[id]; } diff --git a/src/utils/MoneySourceTracker.ts b/src/utils/MoneySourceTracker.ts index 66fdb18a4..891e3389f 100644 --- a/src/utils/MoneySourceTracker.ts +++ b/src/utils/MoneySourceTracker.ts @@ -5,6 +5,7 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; export class MoneySourceTracker { + // eslint-disable-next-line @typescript-eslint/ban-types [key: string]: number | Function; bladeburner = 0; @@ -49,6 +50,7 @@ export class MoneySourceTracker { } // Initiatizes a MoneySourceTracker object from a JSON save state. + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types static fromJSON(value: any): MoneySourceTracker { return Generic_fromJSON(MoneySourceTracker, value.data); } diff --git a/src/utils/helpers/createRandomString.ts b/src/utils/helpers/createRandomString.ts index d963e8a41..97261a919 100644 --- a/src/utils/helpers/createRandomString.ts +++ b/src/utils/helpers/createRandomString.ts @@ -2,7 +2,7 @@ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; export function createRandomString(n: number): string { - let str: string = ""; + let str = ""; for (let i = 0; i < n; ++i) { str += chars.charAt(Math.floor(Math.random() * chars.length)); diff --git a/stylelint.config.js b/stylelint.config.js index 34255608b..6a3a7e05e 100644 --- a/stylelint.config.js +++ b/stylelint.config.js @@ -2,7 +2,7 @@ module.exports = { plugins: [ "stylelint-declaration-use-variable", - "stylelint-order" /*, + "stylelint-order", /*, "stylelint-scss" */ ], rules: { @@ -139,20 +139,20 @@ module.exports = { "custom-properties", { type: "at-rule", - name: "extend" + name: "extend", }, { type: "at-rule", - name: "include" + name: "include", }, "declarations", "rules", "at-rules", - "less-mixins" + "less-mixins", ], { - unspecified: "bottom" - } + unspecified: "bottom", + }, ], // "order/properties-order": [ // [] @@ -162,7 +162,7 @@ module.exports = { "grid-area", "grid-template", "grid-column", - "grid-row" + "grid-row", ], "property-case": "lower", "property-no-unknown": true, @@ -236,7 +236,7 @@ module.exports = { "selector-attribute-operator-space-after": "never", "selector-attribute-operator-space-before": "never", "selector-attribute-operator-whitelist": [ - "=" + "=", ], "selector-attribute-quotes": "always", "selector-class-pattern": ".+", @@ -264,9 +264,9 @@ module.exports = { true, { ignore: [ - "attribute", "class" - ] - } + "attribute", "class", + ], + }, ], "selector-no-vendor-prefix": true, "selector-pseudo-class-blacklist": [], @@ -284,7 +284,7 @@ module.exports = { "not", "last-child", "root", - "visited" + "visited", ], //"selector-pseudo-element-blacklist": [], "selector-pseudo-element-case": "lower", @@ -315,7 +315,7 @@ module.exports = { "ms", "s", "vw", - "%" + "%", ], // "value-keyword-case": "lower", "value-list-comma-newline-after": "always-multi-line", @@ -323,6 +323,6 @@ module.exports = { "value-list-comma-space-after": "always-single-line", "value-list-comma-space-before": "never", "value-list-max-empty-lines": 0, - "value-no-vendor-prefix": true - } + "value-no-vendor-prefix": true, + }, }; diff --git a/test/Netscript/DynamicRamCalculationTests.js b/test/Netscript/DynamicRamCalculationTests.js index e23bc41a3..5552508f0 100644 --- a/test/Netscript/DynamicRamCalculationTests.js +++ b/test/Netscript/DynamicRamCalculationTests.js @@ -34,7 +34,7 @@ describe("Netscript Dynamic RAM Calculation/Generation Tests", function() { function runPotentiallyAsyncFunction(fn) { let res = fn(); if (res instanceof Promise) { - res.catch(() => {}); + res.catch(() => undefined); } } @@ -394,6 +394,16 @@ describe("Netscript Dynamic RAM Calculation/Generation Tests", function() { await testNonzeroDynamicRamCost(f); }); + it("getServerMaxRam()", async function() { + const f = ["getServerMaxRam"]; + await testNonzeroDynamicRamCost(f); + }); + + it("getServerUsedRam()", async function() { + const f = ["getServerUsedRam"]; + await testNonzeroDynamicRamCost(f); + }); + it("serverExists()", async function() { const f = ["serverExists"]; await testNonzeroDynamicRamCost(f); diff --git a/test/Netscript/StaticRamCalculationTests.js b/test/Netscript/StaticRamCalculationTests.js index 6c59d8b7e..bd40a32c3 100644 --- a/test/Netscript/StaticRamCalculationTests.js +++ b/test/Netscript/StaticRamCalculationTests.js @@ -54,7 +54,6 @@ describe("Netscript Static RAM Calculation/Generation Tests", function() { const calculated = await calculateRamUsage(code, []); testEquality(calculated, ScriptBaseCost); - const multipleCallsCode = code.repeat(3); const multipleCallsCalculated = await calculateRamUsage(code, []); expect(multipleCallsCalculated).to.equal(ScriptBaseCost); } @@ -285,6 +284,16 @@ describe("Netscript Static RAM Calculation/Generation Tests", function() { await expectNonZeroRamCost(f); }); + it("getServerMaxRam()", async function() { + const f = ["getServerMaxRam"]; + await expectNonZeroRamCost(f); + }); + + it("getServerUsedRam()", async function() { + const f = ["getServerUsedRam"]; + await expectNonZeroRamCost(f); + }); + it("serverExists()", async function() { const f = ["serverExists"]; await expectNonZeroRamCost(f); diff --git a/test/StockMarketTests.ts b/test/StockMarketTests.ts index bd933478d..10a89f63a 100644 --- a/test/StockMarketTests.ts +++ b/test/StockMarketTests.ts @@ -63,7 +63,7 @@ describe("Stock Market Tests", function() { }; beforeEach(function() { - function construct() { + function construct(): void { stock = new Stock(ctorParams); } @@ -73,13 +73,14 @@ describe("Stock Market Tests", function() { describe("Stock Class", function() { describe("constructor", function() { it("should have default parameters", function() { - let defaultStock: Stock; - function construct() { - defaultStock = new Stock(); + function construct(): void { + new Stock(); // eslint-disable-line no-new } - expect(construct).to.not.throw(); - expect(defaultStock!.name).to.equal(""); + + const defaultStock = new Stock(); + expect(defaultStock).to.not.equal(null); + expect(defaultStock.name).to.equal(""); }); it("should properly initialize props from parameters", function() { @@ -99,7 +100,6 @@ describe("Stock Market Tests", function() { }); it ("should properly initialize props from range-values", function() { - let stock: Stock; const params = { b: true, initPrice: { @@ -126,15 +126,18 @@ describe("Stock Market Tests", function() { symbol: "mock", }; - function construct() { - stock = new Stock(params); + function construct(): void { + new Stock(params); // eslint-disable-line no-new } 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); + + const stock = new Stock(params); + expect(stock).not.equal(null); + 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() { @@ -569,17 +572,19 @@ describe("Stock Market Tests", function() { describe("Forecast Movement Processor Function", function() { // N = 1 is the original forecast - function getNthForecast(origForecast: number, n: number) { + function getNthForecast(origForecast: number, n: number): number { return origForecast - forecastChangePerPriceMovement * (n - 1); } - function getNthForecastForecast(origForecastForecast: number, n: number) { + function getNthForecastForecast(origForecastForecast: number, n: number): number { if (stock.otlkMagForecast > 50) { const expected = origForecastForecast - (forecastChangePerPriceMovement * (n - 1) * (stock.mv / 100)); return expected < 50 ? 50 : expected; } else if (stock.otlkMagForecast < 50) { const expected = origForecastForecast + (forecastChangePerPriceMovement * (n - 1) * (stock.mv / 100)); return expected > 50 ? 50 : expected; + } else { + return 50; } } @@ -838,9 +843,10 @@ describe("Stock Market Tests", function() { const cost = getBuyTransactionCost(stock, shares, PositionTypes.Long); if (cost == null) { expect.fail(); + return; } - Player.setMoney(cost!); + Player.setMoney(cost); expect(buyStock(stock, shares, null, suppressDialogOpt)).to.equal(true); expect(stock.playerShares).to.equal(shares); @@ -932,9 +938,10 @@ describe("Stock Market Tests", function() { const cost = getBuyTransactionCost(stock, shares, PositionTypes.Short); if (cost == null) { expect.fail(); + return } - Player.setMoney(cost!); + Player.setMoney(cost); expect(shortStock(stock, shares, null, suppressDialogOpt)).to.equal(true); expect(stock.playerShortShares).to.equal(shares); @@ -1006,19 +1013,19 @@ describe("Stock Market Tests", function() { describe("Order Class", function() { it("should throw on invalid arguments", function() { - function invalid1() { + function invalid1(): Order { return new Order({} as string, 1, 1, OrderTypes.LimitBuy, PositionTypes.Long); } - function invalid2() { + function invalid2(): Order { return new Order("FOO", "z" as any as number, 0, OrderTypes.LimitBuy, PositionTypes.Short); } - function invalid3() { + function invalid3(): Order { return new Order("FOO", 1, {} as number, OrderTypes.LimitBuy, PositionTypes.Short); } - function invalid4() { + function invalid4(): Order { return new Order("FOO", 1, NaN, OrderTypes.LimitBuy, PositionTypes.Short); } - function invalid5() { + function invalid5(): Order { return new Order("FOO", NaN, 0, OrderTypes.LimitBuy, PositionTypes.Short); } @@ -1089,7 +1096,7 @@ describe("Stock Market Tests", function() { shares: 1e3, price: 9e3, type: OrderTypes.LimitBuy, - pos: PositionTypes.Long + pos: PositionTypes.Long, }); expect(res).to.equal(true); expect(StockMarket["Orders"][stock.symbol]).to.have.lengthOf(0); @@ -1107,7 +1114,7 @@ describe("Stock Market Tests", function() { shares: 999, price: 9e3, type: OrderTypes.LimitBuy, - pos: PositionTypes.Long + pos: PositionTypes.Long, }); expect(res2).to.equal(false); expect(StockMarket["Orders"][stock.symbol]).to.have.lengthOf(1); @@ -1130,20 +1137,20 @@ describe("Stock Market Tests", function() { Player.setMoney(100e9); processOrdersRefs = { - rerenderFn: () => {}, + rerenderFn: () => undefined, stockMarket: StockMarket as IStockMarket, symbolToStockMap: SymbolToStockMap, }; }); - function checkThatOrderExists(placeOrderRes?: boolean) { + function checkThatOrderExists(placeOrderRes?: boolean): void { if (typeof placeOrderRes === "boolean") { expect(placeOrderRes).to.equal(true); } expect(StockMarket["Orders"][stock.symbol]).to.have.lengthOf(1); } - function checkThatOrderExecuted() { + function checkThatOrderExecuted(): void { expect(StockMarket["Orders"][stock.symbol]).to.have.lengthOf(0); } diff --git a/test/StringHelperFunctionsTests.ts b/test/StringHelperFunctionsTests.ts new file mode 100644 index 000000000..2e45f7845 --- /dev/null +++ b/test/StringHelperFunctionsTests.ts @@ -0,0 +1,11 @@ +import { expect } from "chai"; +import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions"; + +describe("StringHelperFunctions Tests", function() { + expect(convertTimeMsToTimeElapsedString(1000)).to.equal("1 seconds"); + expect(convertTimeMsToTimeElapsedString(5*60*1000+34*1000)).to.equal("5 minutes 34 seconds"); + expect(convertTimeMsToTimeElapsedString(2*60*60*24*1000+5*60*1000+34*1000)).to.equal("2 days 5 minutes 34 seconds"); + expect(convertTimeMsToTimeElapsedString(2*60*60*24*1000+5*60*1000+34*1000, true)).to.equal("2 days 5 minutes 34.000 seconds"); + expect(convertTimeMsToTimeElapsedString(2*60*60*24*1000+5*60*1000+34*1000+123, true)).to.equal("2 days 5 minutes 34.123 seconds"); + expect(convertTimeMsToTimeElapsedString(2*60*60*24*1000+5*60*1000+34*1000+123.888, true)).to.equal("2 days 5 minutes 34.123 seconds"); +}) \ No newline at end of file diff --git a/test/Terminal/DirectoryTests.js b/test/Terminal/DirectoryTests.js index e8516ca18..e63136626 100644 --- a/test/Terminal/DirectoryTests.js +++ b/test/Terminal/DirectoryTests.js @@ -286,13 +286,13 @@ describe("Terminal Directory Tests", function() { }); describe("evaluateDirectoryPath()", function() { - const evaluateDirectoryPath = dirHelpers.evaluateDirectoryPath; + //const evaluateDirectoryPath = dirHelpers.evaluateDirectoryPath; // TODO }); describe("evaluateFilePath()", function() { - const evaluateFilePath = dirHelpers.evaluateFilePath; + //const evaluateFilePath = dirHelpers.evaluateFilePath; // TODO }) diff --git a/test/index.js b/test/index.js index 68045825f..3b95de359 100644 --- a/test/index.js +++ b/test/index.js @@ -1,4 +1,5 @@ export * from "./Netscript/DynamicRamCalculationTests"; export * from "./Netscript/StaticRamCalculationTests"; export * from "./StockMarketTests"; +export * from "./StringHelperFunctionsTests"; export * from "./Terminal/DirectoryTests"; diff --git a/utils/DialogBox.d.ts b/utils/DialogBox.d.ts index 7273671cb..87e1ea85a 100644 --- a/utils/DialogBox.d.ts +++ b/utils/DialogBox.d.ts @@ -1,2 +1,2 @@ export function dialogBoxCreate(txt: string | JSX.Element, preformatted?: boolean): void; -export var dialogBoxOpened: boolean; +export let dialogBoxOpened: boolean; diff --git a/utils/DialogBox.jsx b/utils/DialogBox.jsx index 5a93cb23f..56d5daa9c 100644 --- a/utils/DialogBox.jsx +++ b/utils/DialogBox.jsx @@ -31,7 +31,7 @@ function closeTopmostDialogBox() { } // Dialog box close buttons -$(document).on('click', '.dialog-box-close-button', function( event ) { +$(document).on('click', '.dialog-box-close-button', function() { closeTopmostDialogBox(); }); diff --git a/utils/FactionInvitationBox.js b/utils/FactionInvitationBox.js index f6ed35ab6..8150def89 100644 --- a/utils/FactionInvitationBox.js +++ b/utils/FactionInvitationBox.js @@ -20,11 +20,6 @@ function factionInvitationSetText(txt) { textBox.innerHTML = txt; } -function factionInvitationSetMessage(msg) { - var msgBox = document.getElementById("faction-invitation-box-message"); - msgBox.innerHTML = msg; -} - //ram argument is in GB function factionInvitationBoxCreate(faction) { factionInvitationSetText("You have received a faction invitation from " + faction.name); diff --git a/utils/GameOptions.js b/utils/GameOptions.js index ad929a6cc..654a17bdf 100644 --- a/utils/GameOptions.js +++ b/utils/GameOptions.js @@ -23,7 +23,7 @@ function gameOptionsBoxInit() { gameOptionsBoxClose(); return false; }); -}; +} document.addEventListener("DOMContentLoaded", gameOptionsBoxInit, false); diff --git a/utils/InfiltrationBox.js b/utils/InfiltrationBox.js index 59db25098..ab05179cc 100644 --- a/utils/InfiltrationBox.js +++ b/utils/InfiltrationBox.js @@ -4,7 +4,6 @@ import { formatNumber } from "./StringHelperFunctions"; import { BitNodeMultipliers } from "../src/BitNode/BitNodeMultipliers"; import { CONSTANTS } from "../src/Constants"; -import { Faction } from "../src/Faction/Faction"; import { Factions } from "../src/Faction/Factions"; import { Player } from "../src/Player"; diff --git a/utils/JSONReviver.d.ts b/utils/JSONReviver.d.ts index f4405df83..237eb0364 100644 --- a/utils/JSONReviver.d.ts +++ b/utils/JSONReviver.d.ts @@ -1,10 +1,10 @@ interface IReviverValue { ctor: string; - data: object + data: any; } export function Generic_fromJSON(ctor: new () => T, data: any): T; -export function Generic_toJSON(ctorName: string, obj: object, keys?: string[]): string; +export function Generic_toJSON(ctorName: string, obj: any, keys?: string[]): string; export function Reviver(key, value: IReviverValue); export namespace Reviver { - export var constructors: any; + export let constructors: any; } diff --git a/utils/JSONReviver.js b/utils/JSONReviver.js index 8d10ceee5..b23656b86 100644 --- a/utils/JSONReviver.js +++ b/utils/JSONReviver.js @@ -46,7 +46,7 @@ Reviver.constructors = {}; // A list of constructors the smart reviver should kn // 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; + var data, key; if (!keys) { keys = Object.keys(obj); // Only "own" properties are included diff --git a/utils/LogBox.ts b/utils/LogBox.ts index 10633e035..23fce3c59 100644 --- a/utils/LogBox.ts +++ b/utils/LogBox.ts @@ -42,18 +42,18 @@ function logBoxInit(): void { logBoxClose(); document.removeEventListener("DOMContentLoaded", logBoxInit); -}; +} document.addEventListener("DOMContentLoaded", logBoxInit); -function logBoxClose() { +function logBoxClose(): void { logBoxOpened = false; if (logBoxContainer instanceof HTMLElement) { logBoxContainer.style.display = "none"; } } -function logBoxOpen() { +function logBoxOpen(): void { logBoxOpened = true; if (logBoxContainer instanceof HTMLElement) { @@ -64,7 +64,7 @@ function logBoxOpen() { export let logBoxOpened = false; let logBoxCurrentScript: RunningScript | null = null; -export function logBoxCreate(script: RunningScript) { +export function logBoxCreate(script: RunningScript): void { logBoxCurrentScript = script; const killScriptBtn = clearEventListeners("log-box-kill-script"); @@ -92,7 +92,7 @@ export function logBoxCreate(script: RunningScript) { logBoxUpdateText(); } -export function logBoxUpdateText() { +export function logBoxUpdateText(): void { if (!(logText instanceof HTMLElement)) { return; } if (logBoxCurrentScript && logBoxOpened && logBoxCurrentScript.logUpd) { diff --git a/utils/StringHelperFunctions.ts b/utils/StringHelperFunctions.ts index 01a69ce69..90f80fab5 100644 --- a/utils/StringHelperFunctions.ts +++ b/utils/StringHelperFunctions.ts @@ -13,12 +13,13 @@ Converts a date representing time in milliseconds to a string with the format H e.g. 10000 -> "10 seconds" 120000 -> "2 minutes and 0 seconds" */ -function convertTimeMsToTimeElapsedString(time: number): string { - const millisecondsPerSecond: number = 1000; - const secondPerMinute: number = 60; - const minutesPerHours: number = 60; +function convertTimeMsToTimeElapsedString(time: number, showMilli=false): string { + time = Math.floor(time); + const millisecondsPerSecond = 1000; + const secondPerMinute = 60; + const minutesPerHours = 60; const secondPerHours: number = secondPerMinute * minutesPerHours; - const hoursPerDays: number = 24; + const hoursPerDays = 24; const secondPerDay: number = secondPerHours * hoursPerDays; // Convert ms to seconds, since we only have second-level precision @@ -33,9 +34,15 @@ function convertTimeMsToTimeElapsedString(time: number): string { const minutes: number = Math.floor(secTruncHours / secondPerMinute); const secTruncMinutes: number = secTruncHours % secondPerMinute; - const seconds: number = secTruncMinutes; + const milliTruncSec: string = (() => { + let str: string = `${time % millisecondsPerSecond}`; + while(str.length < 3) str = "0"+str; + return str; + })() - let res: string = ""; + const seconds: string = showMilli ? `${secTruncMinutes}.${milliTruncSec}` : `${secTruncMinutes}`; + + let res = ""; if (days > 0) {res += `${days} days `; } if (hours > 0) {res += `${hours} hours `; } if (minutes > 0) {res += `${minutes} minutes `; } @@ -54,7 +61,7 @@ function longestCommonStart(strings: string[]): string { const a1: string = A[0]; const a2: string = A[A.length - 1]; const L: number = a1.length; - let i: number = 0; + let i = 0; const areEqualCaseInsensitive: EqualityFunc = (a: string, b: string) => a.toUpperCase() === b.toUpperCase(); while (i < L && areEqualCaseInsensitive(a1.charAt(i), a2.charAt(i))) { i++; @@ -92,10 +99,10 @@ function isHTML(str: string): boolean { // Generates a random alphanumeric string with N characters function generateRandomString(n: number): string { - let str: string = ""; - const chars: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + let str = ""; + const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - for (let i: number = 0; i < n; i++) { + for (let i = 0; i < n; i++) { str += chars.charAt(Math.floor(Math.random() * chars.length)); } diff --git a/utils/YesNoBox.ts b/utils/YesNoBox.ts index ca1da968f..bbac42b1e 100644 --- a/utils/YesNoBox.ts +++ b/utils/YesNoBox.ts @@ -8,15 +8,14 @@ */ import { clearEventListeners } from "./uiHelpers/clearEventListeners"; import { KEY } from "./helpers/keyCodes"; -import * as React from "react"; import * as ReactDOM from "react-dom"; -export let yesNoBoxOpen: boolean = false; +export let yesNoBoxOpen = false; const yesNoBoxContainer: HTMLElement | null = document.getElementById("yes-no-box-container"); const yesNoBoxTextElement: HTMLElement | null = document.getElementById("yes-no-box-text"); -function yesNoBoxHotkeyHandler(e: KeyboardEvent) { +function yesNoBoxHotkeyHandler(e: KeyboardEvent): void { if (e.keyCode === KEY.ESC) { yesNoBoxClose(); } else if (e.keyCode === KEY.ENTER) { @@ -43,15 +42,15 @@ export function yesNoBoxClose(): boolean { return false; //So that 'return yesNoBoxClose()' is return false in event listeners } -export function yesNoBoxGetYesButton() { +export function yesNoBoxGetYesButton(): HTMLElement | null { return clearEventListeners("yes-no-box-yes"); } -export function yesNoBoxGetNoButton() { +export function yesNoBoxGetNoButton(): HTMLElement | null { return clearEventListeners("yes-no-box-no"); } -export function yesNoBoxCreate(txt: string | JSX.Element) { +export function yesNoBoxCreate(txt: string | JSX.Element): boolean { if (yesNoBoxOpen) { return false; } //Already open yesNoBoxOpen = true; @@ -86,7 +85,7 @@ const yesNoTextInputBoxContainer: HTMLElement | null = document.getElementById(" const yesNoTextInputBoxInput: HTMLInputElement | null = document.getElementById("yes-no-text-input-box-input") as HTMLInputElement; const yesNoTextInputBoxTextElement: HTMLElement | null = document.getElementById("yes-no-text-input-box-text"); -export function yesNoTxtInpBoxHotkeyHandler(e: KeyboardEvent) { +export function yesNoTxtInpBoxHotkeyHandler(e: KeyboardEvent): void { if (e.keyCode === KEY.ESC) { yesNoTxtInpBoxClose(); } else if (e.keyCode === KEY.ENTER) { @@ -106,8 +105,9 @@ export function yesNoTxtInpBoxClose(): boolean { console.error("Container not found for YesNoTextInputBox"); return false; } + if(!yesNoTextInputBoxInput) throw new Error("yesNoTextInputBoxInput was not set"); yesNoBoxOpen = false; - yesNoTextInputBoxInput!.value = ""; + yesNoTextInputBoxInput.value = ""; // Remove hotkey handler document.removeEventListener("keydown", yesNoTxtInpBoxHotkeyHandler); @@ -115,25 +115,29 @@ export function yesNoTxtInpBoxClose(): boolean { return false; } -export function yesNoTxtInpBoxGetYesButton(): HTMLElement | null { - return clearEventListeners("yes-no-text-input-box-yes"); +export function yesNoTxtInpBoxGetYesButton(): HTMLElement { + const elem = clearEventListeners("yes-no-text-input-box-yes"); + if(elem === null) throw new Error("Could not find element with id: 'yes-no-text-input-box-yes'"); + return elem; } -export function yesNoTxtInpBoxGetNoButton(): HTMLElement | null { - return clearEventListeners("yes-no-text-input-box-no"); +export function yesNoTxtInpBoxGetNoButton(): HTMLElement { + const elem = clearEventListeners("yes-no-text-input-box-no"); + if(elem === null) throw new Error("Could not find element with id: 'yes-no-text-input-box-no'"); + return elem; } export function yesNoTxtInpBoxGetInput(): string { - if (yesNoTextInputBoxInput == null) { + if (!yesNoTextInputBoxInput) { console.error("Could not find YesNoTextInputBox input element"); return ""; } - let val: string = yesNoTextInputBoxInput!.value; + let val: string = yesNoTextInputBoxInput.value; val = val.replace(/\s+/g, ''); return val; } -export function yesNoTxtInpBoxCreate(txt: string | JSX.Element) { +export function yesNoTxtInpBoxCreate(txt: string | JSX.Element): void { yesNoBoxOpen = true; @@ -156,5 +160,6 @@ export function yesNoTxtInpBoxCreate(txt: string | JSX.Element) { // Add event listener for Esc and Enter hotkeys document.addEventListener("keydown", yesNoTxtInpBoxHotkeyHandler); - yesNoTextInputBoxInput!.focus(); + if(!yesNoTextInputBoxInput) throw new Error("yesNoTextInputBoxInput was not set"); + yesNoTextInputBoxInput.focus(); } diff --git a/utils/helpers/addOffset.ts b/utils/helpers/addOffset.ts index a45ababd4..2463a8aff 100644 --- a/utils/helpers/addOffset.ts +++ b/utils/helpers/addOffset.ts @@ -9,8 +9,8 @@ * @param midpoint The number to be the midpoint of the offset range * @param percentage The percentage (in a range of 0-100) to offset */ -export function addOffset(midpoint: number, percentage: number) { - const maxPercent: number = 100; +export function addOffset(midpoint: number, percentage: number): number { + const maxPercent = 100; if (percentage < 0 || percentage > maxPercent) { return midpoint; } diff --git a/utils/helpers/arrayToString.ts b/utils/helpers/arrayToString.ts index 815dd4495..f301c6563 100644 --- a/utils/helpers/arrayToString.ts +++ b/utils/helpers/arrayToString.ts @@ -5,7 +5,7 @@ * - Adds brackets around the array * - Adds quotation marks around strings */ -export function arrayToString(a: T[]) { +export function arrayToString(a: T[]): string { const vals: any[] = []; for (let i = 0; i < a.length; ++i) { let elem: any = a[i]; diff --git a/utils/helpers/clearObject.ts b/utils/helpers/clearObject.ts index fec858b20..57a92b6f4 100644 --- a/utils/helpers/clearObject.ts +++ b/utils/helpers/clearObject.ts @@ -4,7 +4,8 @@ * @deprecated Look into using `Map` or `Set` rather than manipulating properties on an Object. * @param obj the object to clear all properties */ -export function clearObject(obj: any) { + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export function clearObject(obj: any): void { for (const key in obj) { if (obj.hasOwnProperty(key)) { // tslint:disable-next-line:no-dynamic-delete diff --git a/utils/helpers/compareArrays.ts b/utils/helpers/compareArrays.ts index 257b2912a..8b88caf13 100644 --- a/utils/helpers/compareArrays.ts +++ b/utils/helpers/compareArrays.ts @@ -4,7 +4,7 @@ * @param a1 The first array * @param a2 The second array */ -export function compareArrays(a1: T[], a2: T[]) { +export function compareArrays(a1: T[], a2: T[]): boolean { if (a1.length !== a2.length) { return false; } diff --git a/utils/helpers/createProgressBarText.ts b/utils/helpers/createProgressBarText.ts index 37f433a00..2107de5eb 100644 --- a/utils/helpers/createProgressBarText.ts +++ b/utils/helpers/createProgressBarText.ts @@ -26,7 +26,7 @@ interface IProgressBarConfigurationMaterialized extends IProgressBarConfiguratio * e.g.: [||||---------------] * @param params The configuration parameters for the progress bar */ -export function createProgressBarText(params: IProgressBarConfiguration) { +export function createProgressBarText(params: IProgressBarConfiguration): string { // Default values const defaultParams: IProgressBarConfigurationMaterialized = { progress: 0, diff --git a/utils/helpers/exceptionAlert.ts b/utils/helpers/exceptionAlert.ts index 2a6998c89..5130b2fb5 100644 --- a/utils/helpers/exceptionAlert.ts +++ b/utils/helpers/exceptionAlert.ts @@ -1,8 +1,8 @@ import { dialogBoxCreate } from "../DialogBox"; interface IError { - fileName?: string, - lineNumber?: number, + fileName?: string; + lineNumber?: number; } export function exceptionAlert(e: IError): void { diff --git a/utils/helpers/getRandomByte.ts b/utils/helpers/getRandomByte.ts index 5b6ddf57d..954d45d83 100644 --- a/utils/helpers/getRandomByte.ts +++ b/utils/helpers/getRandomByte.ts @@ -4,9 +4,9 @@ import { getRandomInt } from "./getRandomInt"; * Gets a random value in the range of a byte (0 - 255), or up to the maximum. * @param max The maximum value (up to 255). */ -export function getRandomByte(max: number) { +export function getRandomByte(max: number): number { // Technically 2^8 is 256, but the values are 0-255, not 1-256. - const byteMaximum: number = 255; + const byteMaximum = 255; const upper: number = Math.max(Math.min(max, byteMaximum), 0); return getRandomInt(0, upper); diff --git a/utils/helpers/getRandomInt.ts b/utils/helpers/getRandomInt.ts index 4f5dc15b5..1dc4956f1 100644 --- a/utils/helpers/getRandomInt.ts +++ b/utils/helpers/getRandomInt.ts @@ -3,7 +3,7 @@ * @param min The minimum value in the range. * @param max The maximum value in the range. */ -export function getRandomInt(min: number, max: number) { +export function getRandomInt(min: number, max: number): number { const lower: number = Math.min(min, max); const upper: number = Math.max(min, max); diff --git a/utils/helpers/getTimestamp.ts b/utils/helpers/getTimestamp.ts index 6e7ee119f..bd523f727 100644 --- a/utils/helpers/getTimestamp.ts +++ b/utils/helpers/getTimestamp.ts @@ -1,10 +1,10 @@ /** * Returns a MM/DD HH:MM timestamp for the current time */ -export function getTimestamp() { +export function getTimestamp(): string { const d: Date = new Date(); // A negative slice value takes from the end of the string rather than the beginning. - const stringWidth: number = -2; + const stringWidth = -2; const formattedHours: string = `0${d.getHours()}`.slice(stringWidth); const formattedMinutes: string = `0${d.getMinutes()}`.slice(stringWidth); diff --git a/utils/helpers/isPowerOfTwo.ts b/utils/helpers/isPowerOfTwo.ts index 6f98ccf83..c0822c704 100644 --- a/utils/helpers/isPowerOfTwo.ts +++ b/utils/helpers/isPowerOfTwo.ts @@ -2,7 +2,7 @@ * Determines if the number is a power of 2 * @param n The number to check. */ -export function isPowerOfTwo(n: number) { +export function isPowerOfTwo(n: number): boolean { if (isNaN(n)) { return false; } diff --git a/utils/helpers/isString.ts b/utils/helpers/isString.ts index 5d24bc197..204d42427 100644 --- a/utils/helpers/isString.ts +++ b/utils/helpers/isString.ts @@ -2,6 +2,7 @@ * Checks whether the value passed in can be considered a string. * @param value The value to check if it is a string. */ +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export function isString(value: any): boolean { return (typeof value === "string" || value instanceof String); } diff --git a/utils/helpers/isValidIPAddress.ts b/utils/helpers/isValidIPAddress.ts index 67b40257f..47afdbb43 100644 --- a/utils/helpers/isValidIPAddress.ts +++ b/utils/helpers/isValidIPAddress.ts @@ -3,10 +3,10 @@ * Checks whether a IP Address string is valid. * @param ipaddress A string representing a potential IP Address */ -export function isValidIPAddress(ipaddress: string) { - const byteRange: string = "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"; - const regexStr: string = `^${byteRange}\.${byteRange}\.${byteRange}\.${byteRange}$`; - const ipAddressRegex: RegExp = new RegExp(regexStr); +export function isValidIPAddress(ipaddress: string): boolean { + const byteRange = "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"; + const regexStr = `^${byteRange}\.${byteRange}\.${byteRange}\.${byteRange}$`; + const ipAddressRegex = new RegExp(regexStr); return ipAddressRegex.test(ipaddress); } diff --git a/utils/helpers/roundToTwo.ts b/utils/helpers/roundToTwo.ts index 33053ec61..a7fa1c2fb 100644 --- a/utils/helpers/roundToTwo.ts +++ b/utils/helpers/roundToTwo.ts @@ -2,7 +2,7 @@ * Rounds a number to two decimal places. * @param decimal A decimal value to trim to two places. */ -export function roundToTwo(decimal: number) { +export function roundToTwo(decimal: number): number { const leftShift: number = Math.round(parseFloat(`${decimal}e+2`)); return +(`${leftShift}e-2`); diff --git a/utils/uiHelpers/appendLineBreaks.ts b/utils/uiHelpers/appendLineBreaks.ts index f2895c536..02ac2ca1e 100644 --- a/utils/uiHelpers/appendLineBreaks.ts +++ b/utils/uiHelpers/appendLineBreaks.ts @@ -5,8 +5,8 @@ import { createElement } from "./createElement"; * @param el The element to add child break elements to. * @param n The number of breaks to add. */ -export function appendLineBreaks(el: HTMLElement, n: number) { - for (let i: number = 0; i < n; ++i) { +export function appendLineBreaks(el: HTMLElement, n: number): void { + for (let i = 0; i < n; ++i) { el.appendChild(createElement("br")); } } diff --git a/utils/uiHelpers/clearSelector.ts b/utils/uiHelpers/clearSelector.ts index 39e087bc0..887f72a53 100644 --- a/utils/uiHelpers/clearSelector.ts +++ b/utils/uiHelpers/clearSelector.ts @@ -2,7 +2,7 @@ * Clears all