fmt, remove corp routing, lint

This commit is contained in:
Olivier Gagnon 2021-09-06 15:06:08 -04:00
parent 91434b7972
commit 506122f5b8
53 changed files with 1300 additions and 1610 deletions

@ -1,366 +1,434 @@
const numSpaces = 4;
const maxLineLength = 160;
module.exports = {
env: {
node: true,
es6: true,
},
extends: "eslint:recommended",
parserOptions: {
ecmaVersion: 8,
sourceType: "module",
ecmaFeatures: {
experimentalObjectRestSpread: true,
"env": {
"es6": true,
"node": true
},
},
rules: {
"accessor-pairs": [
"error",
{
setWithoutGet: true,
getWithoutSet: false,
},
],
"array-bracket-newline": ["error"],
"array-bracket-spacing": ["error"],
"array-callback-return": ["error"],
"array-element-newline": ["error"],
"arrow-body-style": ["error"],
"arrow-parens": ["error"],
"arrow-spacing": ["error"],
"block-scoped-var": ["error"],
"block-spacing": ["error"],
"brace-style": ["error"],
"callback-return": ["error"],
camelcase: ["error"],
"capitalized-comments": ["error"],
"class-methods-use-this": ["error"],
"comma-dangle": ["error"],
"comma-spacing": ["error"],
"comma-style": ["error", "last"],
complexity: ["error"],
"computed-property-spacing": ["error", "never"],
"consistent-return": ["error"],
"consistent-this": ["error"],
"constructor-super": ["error"],
curly: ["error"],
"default-case": ["error"],
"dot-location": ["error", "property"],
"dot-notation": ["error"],
"eol-last": ["error"],
eqeqeq: ["error"],
"for-direction": ["error"],
"func-call-spacing": ["error"],
"func-name-matching": ["error"],
"func-names": ["error", "never"],
"func-style": ["error"],
"function-paren-newline": ["error"],
"generator-star-spacing": ["error", "before"],
"getter-return": [
"error",
{
allowImplicit: false,
},
],
"global-require": ["error"],
"guard-for-in": ["error"],
"handle-callback-err": ["error"],
"id-blacklist": ["error"],
"id-length": ["error"],
"id-match": ["error"],
"implicit-arrow-linebreak": ["error", "beside"],
indent: [
"error",
4,
{
SwitchCase: 1,
},
],
"init-declarations": ["error"],
"jsx-quotes": ["error"],
"key-spacing": ["error"],
"keyword-spacing": ["error"],
"line-comment-position": ["error"],
"linebreak-style": ["error", "windows"],
"lines-around-comment": ["error"],
"lines-between-class-members": ["error"],
"max-depth": ["error"],
"max-len": ["error", 160],
"max-lines": [
"error",
{
skipBlankLines: true,
skipComments: true,
},
],
"max-nested-callbacks": ["error"],
"max-params": ["error"],
"max-statements": ["error"],
"max-statements-per-line": ["error"],
"multiline-comment-style": ["off", "starred-block"],
"multiline-ternary": ["error", "never"],
"new-cap": ["error"],
"new-parens": ["error"],
"newline-before-return": [
"error", // TODO: configure this...
],
"newline-per-chained-call": ["error"],
"no-alert": ["error"],
"no-array-constructor": ["error"],
"no-await-in-loop": ["error"],
"no-bitwise": ["error"],
"no-buffer-constructor": ["error"],
"no-caller": ["error"],
"no-case-declarations": ["error"],
"no-catch-shadow": ["error"],
"no-class-assign": ["error"],
"no-compare-neg-zero": ["error"],
"no-cond-assign": ["error", "except-parens"],
"no-confusing-arrow": ["error"],
"no-console": ["error"],
"no-const-assign": ["error"],
"no-constant-condition": [
"error",
{
checkLoops: false,
},
],
"no-continue": ["off"],
"no-control-regex": ["error"],
"no-debugger": ["error"],
"no-delete-var": ["error"],
"no-div-regex": ["error"],
"no-dupe-args": ["error"],
"no-dupe-class-members": ["error"],
"no-dupe-keys": ["error"],
"no-duplicate-case": ["error"],
"no-duplicate-imports": [
"error",
{
includeExports: true,
},
],
"no-else-return": ["error"],
"no-empty": [
"error",
{
allowEmptyCatch: false,
},
],
"no-empty-character-class": ["error"],
"no-empty-function": ["error"],
"no-empty-pattern": ["error"],
"no-eq-null": ["error"],
"no-ex-assign": ["error"],
"no-extra-boolean-cast": ["error"],
"no-extra-parens": [
"error",
"all",
{
conditionalAssign: false,
},
],
"no-extra-semi": ["error"],
"no-eval": ["error"],
"no-extend-native": ["error"],
"no-extra-bind": ["error"],
"no-extra-label": ["error"],
"no-extra-parens": ["error"],
"no-fallthrough": ["error"],
"no-floating-decimal": ["error"],
"no-func-assign": ["error"],
"no-global-assign": ["error"],
"no-implicit-coercion": ["error"],
"no-implicit-globals": ["error"],
"no-implied-eval": ["error"],
"no-inline-comments": ["error"],
"no-inner-declarations": ["error", "both"],
"no-invalid-regexp": ["error"],
"no-invalid-this": ["error"],
"no-irregular-whitespace": [
"error",
{
skipStrings: false,
skipComments: false,
skipRegExps: false,
skipTemplates: false,
},
],
"no-iterator": ["error"],
"no-label-var": ["error"],
"no-labels": ["error"],
"no-lone-blocks": ["error"],
"no-lonely-if": ["error"],
"no-loop-func": ["error"],
"no-magic-numbers": [
"error",
{
ignore: [-1, 0, 1],
ignoreArrayIndexes: true,
},
],
"no-mixed-operators": ["error"],
"no-mixed-requires": ["error"],
"no-mixed-spaces-and-tabs": ["error"],
"no-multi-assign": ["error"],
"no-multi-spaces": ["error"],
"no-multi-str": ["error"],
"no-multiple-empty-lines": [
"error",
{
max: 1,
},
],
"no-native-reassign": ["error"],
"no-negated-condition": ["error"],
"no-negated-in-lhs": ["error"],
"no-nested-ternary": ["error"],
"no-new": ["error"],
"no-new-func": ["error"],
"no-new-object": ["error"],
"no-new-require": ["error"],
"no-new-symbol": ["error"],
"no-new-wrappers": ["error"],
"no-octal": ["error"],
"no-octal-escape": ["error"],
"no-obj-calls": ["error"],
"no-param-reassign": ["error"],
"no-path-concat": ["error"],
"no-plusplus": [
"error",
{
allowForLoopAfterthoughts: true,
},
],
"no-process-env": ["error"],
"no-process-exit": ["error"],
"no-proto": ["error"],
"no-prototype-builtins": ["error"],
"no-redeclare": ["error"],
"no-regex-spaces": ["error"],
"no-restricted-globals": ["error"],
"no-restricted-imports": ["error"],
"no-restricted-modules": ["error"],
"no-restricted-properties": [
"error",
{
object: "console",
property: "log",
message: "'log' is too general, use an appropriate level when logging.",
},
],
"no-restricted-syntax": ["error"],
"no-return-assign": ["error"],
"no-return-await": ["error"],
"no-script-url": ["error"],
"no-self-assign": [
"error",
{
props: false,
},
],
"no-self-compare": ["error"],
"no-sequences": ["error"],
"no-shadow": ["error"],
"no-shadow-restricted-names": ["error"],
"no-spaced-func": ["error"],
"no-sparse-arrays": ["error"],
"no-sync": ["error"],
"no-tabs": ["error"],
"no-template-curly-in-string": ["error"],
"no-ternary": ["off"],
"no-this-before-super": ["error"],
"no-throw-literal": ["error"],
"no-trailing-spaces": ["error"],
"no-undef": ["error"],
"no-undef-init": ["error"],
"no-undefined": ["error"],
"no-underscore-dangle": ["error"],
"no-unexpected-multiline": ["error"],
"no-unmodified-loop-condition": ["error"],
"no-unneeded-ternary": ["error"],
"no-unreachable": ["error"],
"no-unsafe-finally": ["error"],
"no-unsafe-negation": ["error"],
"no-unused-expressions": ["error"],
"no-unused-labels": ["error"],
"no-unused-vars": ["error"],
"no-use-before-define": ["error"],
"no-useless-call": ["error"],
"no-useless-computed-key": ["error"],
"no-useless-concat": ["error"],
"no-useless-constructor": ["error"],
"no-useless-escape": ["error"],
"no-useless-rename": [
"error",
{
ignoreDestructuring: false,
ignoreExport: false,
ignoreImport: false,
},
],
"no-useless-return": ["error"],
"no-var": ["error"],
"no-void": ["error"],
"no-warning-comments": ["error"],
"no-whitespace-before-property": ["error"],
"no-with": ["error"],
"nonblock-statement-body-position": ["error", "below"],
"object-curly-newline": ["error"],
"object-curly-spacing": ["error"],
"object-property-newline": ["error"],
"object-shorthand": ["error"],
"one-var": ["off"],
"one-var-declaration-per-line": ["error"],
"operator-assignment": ["error"],
"operator-linebreak": ["error", "none"],
"padded-blocks": ["off"],
"padding-line-between-statements": ["error"],
"prefer-arrow-callback": ["error"],
"prefer-const": ["error"],
"prefer-destructuring": ["off"],
"prefer-numeric-literals": ["error"],
"prefer-promise-reject-errors": ["off"],
"prefer-reflect": ["error"],
"prefer-rest-params": ["error"],
"prefer-spread": ["error"],
"prefer-template": ["error"],
"quote-props": ["error"],
quotes: ["error"],
radix: ["error", "as-needed"],
"require-await": ["error"],
"require-jsdoc": ["off"],
"require-yield": ["error"],
"rest-spread-spacing": ["error", "never"],
semi: ["error"],
"semi-spacing": ["error"],
"semi-style": ["error", "last"],
"sort-imports": ["error"],
"sort-keys": ["error"],
"sort-vars": ["error"],
"space-before-blocks": ["error"],
"space-before-function-paren": ["off"],
"space-in-parens": ["error"],
"space-infix-ops": ["error"],
"space-unary-ops": ["error"],
"spaced-comment": ["error"],
strict: ["error"],
"switch-colon-spacing": [
"error",
{
after: true,
before: false,
},
],
"symbol-description": ["error"],
"template-curly-spacing": ["error"],
"template-tag-spacing": ["error"],
"unicode-bom": ["error", "never"],
"use-isnan": ["error"],
"valid-jsdoc": ["error"],
"valid-typeof": ["error"],
"vars-on-top": ["error"],
"wrap-iife": ["error", "any"],
"wrap-regex": ["error"],
"yield-star-spacing": ["error", "before"],
yoda: ["error", "never"],
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
},
"ecmaVersion": 8,
"sourceType": "module"
},
"rules": {
"accessor-pairs": [
"error",
{
"getWithoutSet": false,
"setWithoutGet": true
}
],
"array-bracket-newline": ["error"],
"array-bracket-spacing": ["error"],
"array-callback-return": ["error"],
"array-element-newline": ["error"],
"arrow-body-style": ["error"],
"arrow-parens": ["error"],
"arrow-spacing": ["error"],
"block-scoped-var": ["error"],
"block-spacing": ["error"],
"brace-style": ["error"],
"callback-return": ["error"],
"camelcase": ["error"],
"capitalized-comments": ["error"],
"class-methods-use-this": ["error"],
"comma-dangle": ["error"],
"comma-spacing": ["error"],
"comma-style": [
"error",
"last"
],
"complexity": ["error"],
"computed-property-spacing": [
"error",
"never"
],
"consistent-return": ["error"],
"consistent-this": ["error"],
"constructor-super": ["error"],
"curly": ["error"],
"default-case": ["error"],
"dot-location": [
"error",
"property"
],
"dot-notation": ["error"],
"eol-last": ["error"],
"eqeqeq": ["error"],
"for-direction": ["error"],
"func-call-spacing": ["error"],
"func-name-matching": ["error"],
"func-names": [
"error",
"never"
],
"func-style": ["error"],
"function-paren-newline": ["error"],
"generator-star-spacing": [
"error",
"before"
],
"getter-return": [
"error",
{
"allowImplicit": false
}
],
"global-require": ["error"],
"guard-for-in": ["error"],
"handle-callback-err": ["error"],
"id-blacklist": ["error"],
"id-length": ["error"],
"id-match": ["error"],
"implicit-arrow-linebreak": [
"error",
"beside"
],
"indent": [
"error",
numSpaces,
{
"SwitchCase": 1
}
],
"init-declarations": ["error"],
"jsx-quotes": ["error"],
"key-spacing": ["error"],
"keyword-spacing": ["error"],
"line-comment-position": ["error"],
"linebreak-style": [
"error",
"windows"
],
"lines-around-comment": ["error"],
"lines-between-class-members": ["error"],
"max-depth": ["error"],
"max-len": [
"error",
maxLineLength
],
"max-lines": [
"error",
{
"skipBlankLines": true,
"skipComments": true
}
],
"max-nested-callbacks": ["error"],
"max-params": ["error"],
"max-statements": ["error"],
"max-statements-per-line": ["error"],
"multiline-comment-style": [
"off",
"starred-block"
],
"multiline-ternary": [
"error",
"never"
],
"new-cap": ["error"],
"new-parens": ["error"],
// TODO: configure this...
"newline-before-return": ["error"],
"newline-per-chained-call": ["error"],
"no-alert": ["error"],
"no-array-constructor": ["error"],
"no-await-in-loop": ["error"],
"no-bitwise": ["error"],
"no-buffer-constructor": ["error"],
"no-caller": ["error"],
"no-case-declarations": ["error"],
"no-catch-shadow": ["error"],
"no-class-assign": ["error"],
"no-compare-neg-zero": ["error"],
"no-cond-assign": [
"error",
"except-parens"
],
"no-confusing-arrow": ["error"],
"no-console": ["error"],
"no-const-assign": ["error"],
"no-constant-condition": [
"error",
{
"checkLoops": false
}
],
"no-continue": ["off"],
"no-control-regex": ["error"],
"no-debugger": ["error"],
"no-delete-var": ["error"],
"no-div-regex": ["error"],
"no-dupe-args": ["error"],
"no-dupe-class-members": ["error"],
"no-dupe-keys": ["error"],
"no-duplicate-case": ["error"],
"no-duplicate-imports": [
"error",
{
"includeExports": true
}
],
"no-else-return": ["error"],
"no-empty": [
"error",
{
"allowEmptyCatch": false
}
],
"no-empty-character-class": ["error"],
"no-empty-function": ["error"],
"no-empty-pattern": ["error"],
"no-eq-null": ["error"],
"no-eval": ["error"],
"no-ex-assign": ["error"],
"no-extend-native": ["error"],
"no-extra-bind": ["error"],
"no-extra-boolean-cast": ["error"],
"no-extra-label": ["error"],
"no-extra-parens": [
"error",
"all",
{
"conditionalAssign": false
}
],
"no-extra-semi": ["error"],
"no-fallthrough": ["error"],
"no-floating-decimal": ["error"],
"no-func-assign": ["error"],
"no-global-assign": ["error"],
"no-implicit-coercion": ["error"],
"no-implicit-globals": ["error"],
"no-implied-eval": ["error"],
"no-inline-comments": ["error"],
"no-inner-declarations": [
"error",
"both"
],
"no-invalid-regexp": ["error"],
"no-invalid-this": ["error"],
"no-irregular-whitespace": [
"error",
{
"skipComments": false,
"skipRegExps": false,
"skipStrings": false,
"skipTemplates": false
}
],
"no-iterator": ["error"],
"no-label-var": ["error"],
"no-labels": ["error"],
"no-lone-blocks": ["error"],
"no-lonely-if": ["error"],
"no-loop-func": ["error"],
"no-magic-numbers": [
"error",
{
"ignore": [
-1,
0,
1
],
"ignoreArrayIndexes": true
}
],
"no-mixed-operators": ["error"],
"no-mixed-requires": ["error"],
"no-mixed-spaces-and-tabs": ["error"],
"no-multi-assign": ["error"],
"no-multi-spaces": ["error"],
"no-multi-str": ["error"],
"no-multiple-empty-lines": [
"error",
{
"max": 1
}
],
"no-native-reassign": ["error"],
"no-negated-condition": ["error"],
"no-negated-in-lhs": ["error"],
"no-nested-ternary": ["error"],
"no-new": ["error"],
"no-new-func": ["error"],
"no-new-object": ["error"],
"no-new-require": ["error"],
"no-new-symbol": ["error"],
"no-new-wrappers": ["error"],
"no-obj-calls": ["error"],
"no-octal": ["error"],
"no-octal-escape": ["error"],
"no-param-reassign": ["error"],
"no-path-concat": ["error"],
"no-plusplus": [
"error",
{
"allowForLoopAfterthoughts": true
}
],
"no-process-env": ["error"],
"no-process-exit": ["error"],
"no-proto": ["error"],
"no-prototype-builtins": ["error"],
"no-redeclare": ["error"],
"no-regex-spaces": ["error"],
"no-restricted-globals": ["error"],
"no-restricted-imports": ["error"],
"no-restricted-modules": ["error"],
"no-restricted-properties": [
"error",
{
"message": "'log' is too general, use an appropriate level when logging.",
"object": "console",
"property": "log"
}
],
"no-restricted-syntax": ["error"],
"no-return-assign": ["error"],
"no-return-await": ["error"],
"no-script-url": ["error"],
"no-self-assign": [
"error",
{
"props": false
}
],
"no-self-compare": ["error"],
"no-sequences": ["error"],
"no-shadow": ["error"],
"no-shadow-restricted-names": ["error"],
"no-spaced-func": ["error"],
"no-sparse-arrays": ["error"],
"no-sync": ["error"],
"no-tabs": ["error"],
"no-template-curly-in-string": ["error"],
"no-ternary": ["off"],
"no-this-before-super": ["error"],
"no-throw-literal": ["error"],
"no-trailing-spaces": ["error"],
"no-undef": ["error"],
"no-undef-init": ["error"],
"no-undefined": ["error"],
"no-underscore-dangle": ["error"],
"no-unexpected-multiline": ["error"],
"no-unmodified-loop-condition": ["error"],
"no-unneeded-ternary": ["error"],
"no-unreachable": ["error"],
"no-unsafe-finally": ["error"],
"no-unsafe-negation": ["error"],
"no-unused-expressions": ["error"],
"no-unused-labels": ["error"],
"no-unused-vars": ["error"],
"no-use-before-define": ["error"],
"no-useless-call": ["error"],
"no-useless-computed-key": ["error"],
"no-useless-concat": ["error"],
"no-useless-constructor": ["error"],
"no-useless-escape": ["error"],
"no-useless-rename": [
"error",
{
"ignoreDestructuring": false,
"ignoreExport": false,
"ignoreImport": false
}
],
"no-useless-return": ["error"],
"no-var": ["error"],
"no-void": ["error"],
"no-warning-comments": ["error"],
"no-whitespace-before-property": ["error"],
"no-with": ["error"],
"nonblock-statement-body-position": [
"error",
"below"
],
"object-curly-newline": ["error"],
"object-curly-spacing": ["error"],
"object-property-newline": ["error"],
"object-shorthand": ["error"],
"one-var": ["off"],
"one-var-declaration-per-line": ["error"],
"operator-assignment": ["error"],
"operator-linebreak": [
"error",
"none"
],
"padded-blocks": ["off"],
"padding-line-between-statements": ["error"],
"prefer-arrow-callback": ["error"],
"prefer-const": ["error"],
"prefer-destructuring": ["off"],
"prefer-numeric-literals": ["error"],
"prefer-promise-reject-errors": ["off"],
"prefer-reflect": ["error"],
"prefer-rest-params": ["error"],
"prefer-spread": ["error"],
"prefer-template": ["error"],
"quote-props": ["error"],
"quotes": ["error"],
"radix": [
"error",
"as-needed"
],
"require-await": ["error"],
"require-jsdoc": ["off"],
"require-yield": ["error"],
"rest-spread-spacing": [
"error",
"never"
],
"semi": ["error"],
"semi-spacing": ["error"],
"semi-style": [
"error",
"last"
],
"sort-imports": ["error"],
"sort-keys": ["error"],
"sort-vars": ["error"],
"space-before-blocks": ["error"],
"space-before-function-paren": ["off"],
"space-in-parens": ["error"],
"space-infix-ops": ["error"],
"space-unary-ops": ["error"],
"spaced-comment": ["error"],
"strict": ["error"],
"switch-colon-spacing": [
"error",
{
"after": true,
"before": false
}
],
"symbol-description": ["error"],
"template-curly-spacing": ["error"],
"template-tag-spacing": ["error"],
"unicode-bom": [
"error",
"never"
],
"use-isnan": ["error"],
"valid-jsdoc": ["error"],
"valid-typeof": ["error"],
"vars-on-top": ["error"],
"wrap-iife": [
"error",
"any"
],
"wrap-regex": ["error"],
"yield-star-spacing": [
"error",
"before"
],
"yoda": [
"error",
"never"
]
}
};

@ -8,74 +8,66 @@ const path = require("path");
const exec = require("child_process").exec;
const semver = require("./semver");
const getPackageJson = () =>
new Promise((resolve, reject) => {
const getPackageJson = () => new Promise((resolve, reject) => {
try {
/* eslint-disable-next-line global-require */
resolve(require(path.resolve(process.cwd(), "package.json")));
/* eslint-disable-next-line global-require */
resolve(require(path.resolve(process.cwd(), "package.json")));
} catch (error) {
reject(error);
reject(error);
}
});
});
const getEngines = (data) =>
new Promise((resolve, reject) => {
const getEngines = (data) => new Promise((resolve, reject) => {
let versions = null;
if (data.engines) {
versions = data.engines;
versions = data.engines;
}
if (versions) {
resolve(versions);
resolve(versions);
} else {
reject("Missing or improper 'engines' property in 'package.json'");
reject("Missing or improper 'engines' property in 'package.json'");
}
});
});
const checkNpmVersion = (engines) =>
new Promise((resolve, reject) => {
const checkNpmVersion = (engines) => new Promise((resolve, reject) => {
exec("npm -v", (error, stdout, stderr) => {
if (error) {
reject(`Unable to find NPM version\n${stderr}`);
}
if (error) {
reject(`Unable to find NPM version\n${stderr}`);
}
const npmVersion = stdout.trim();
const engineVersion = engines.npm || ">=0";
const npmVersion = stdout.trim();
const engineVersion = engines.npm || ">=0";
if (semver.satisfies(npmVersion, engineVersion)) {
resolve();
} else {
reject(
`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`,
);
}
if (semver.satisfies(npmVersion, engineVersion)) {
resolve();
} else {
reject(`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`);
}
});
});
});
const checkNodeVersion = (engines) =>
new Promise((resolve, reject) => {
const checkNodeVersion = (engines) => new Promise((resolve, reject) => {
const nodeVersion = process.version.substring(1);
if (semver.satisfies(nodeVersion, engines.node)) {
resolve(engines);
resolve(engines);
} else {
reject(
`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`,
);
reject(`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`);
}
});
});
getPackageJson()
.then(getEngines)
.then(checkNodeVersion)
.then(checkNpmVersion)
.then(
() => true,
(error) => {
// Specifically disable these as the error message gets lost in the normal unhandled output.
/* eslint-disable no-console, no-process-exit */
console.error(error);
process.exit(1);
},
);
.then(getEngines)
.then(checkNodeVersion)
.then(checkNpmVersion)
.then(
() => true,
(error) => {
// Specifically disable these as the error message gets lost in the normal unhandled output.
/* eslint-disable no-console, no-process-exit */
console.error(error);
process.exit(1);
}
);

File diff suppressed because it is too large Load Diff

@ -139,8 +139,7 @@ function initAugmentations() {
"unpredictable results based on your circadian rhythm.",
};
Object.keys(randomBonuses.bonuses).forEach(
(key) =>
(UnstableCircadianModulatorParams[key] = randomBonuses.bonuses[key]),
(key) => (UnstableCircadianModulatorParams[key] = randomBonuses.bonuses[key]),
);
const UnstableCircadianModulator = new Augmentation(
UnstableCircadianModulatorParams,

@ -2472,9 +2472,10 @@ export class Bladeburner implements IBladeburner {
case ActionTypes["Diplomacy"]:
case ActionTypes["Hyperbolic Regeneration Chamber"]:
return [1, 1];
case ActionTypes["Recruitment"]:
case ActionTypes["Recruitment"]: {
const recChance = this.getRecruitmentSuccessChance(player);
return [recChance, recChance];
}
default:
workerScript.log(
"bladeburner.getActionEstimatedSuccessChance",

@ -22,8 +22,7 @@ export function BlackOpList(props: IProps): React.ReactElement {
});
blackops = blackops.filter(
(blackop: BlackOperation, i: number) =>
!(
(blackop: BlackOperation, i: number) => !(
props.bladeburner.blackops[blackops[i].name] == null &&
i !== 0 &&
props.bladeburner.blackops[blackops[i - 1].name] == null

@ -2,7 +2,6 @@ import * as React from "react";
import { BlackOpList } from "./BlackOpList";
import { IBladeburner } from "../IBladeburner";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { CopyableText } from "../../ui/React/CopyableText";
interface IProps {
bladeburner: IBladeburner;

@ -26,7 +26,6 @@ export function ContractElem(props: IProps): React.ReactElement {
const estimatedSuccessChance = props.action.getEstSuccessChance(
props.bladeburner,
);
const successChance = props.action.getSuccessChance(props.bladeburner);
const computedActionTimeCurrent = Math.min(
props.bladeburner.actionTimeCurrent + props.bladeburner.actionTimeOverflow,
props.bladeburner.actionTimeToComplete,

@ -3,8 +3,6 @@
*
* Constants for specific mechanics or features will NOT be here.
*/
import { IMap } from "./types";
export const CONSTANTS: {
Version: string;
_idleSpeed: number;

@ -25,7 +25,7 @@ export function NewIndustry(
const cost = IndustryStartingCosts[industry];
if (cost === undefined) {
throw new Error("Invalid industry: ${industry}");
throw new Error(`Invalid industry: '${industry}'`);
}
if (corporation.funds.lt(cost)) {
throw new Error(

@ -32,7 +32,6 @@ import { removeElementById } from "../../utils/uiHelpers/removeElementById";
import React from "react";
import ReactDOM from "react-dom";
import { CorporationRoot } from "./ui/Root";
import { CorporationRouting } from "./ui/Routing";
import Decimal from "decimal.js";
@ -40,7 +39,6 @@ interface IParams {
name?: string;
}
let corpRouting: CorporationRouting;
let companyManagementDiv: HTMLDivElement | null = null;
export class Corporation {
@ -483,22 +481,20 @@ export class Corporation {
const game = document.getElementById("entire-game-container");
if (game) game.appendChild(companyManagementDiv);
corpRouting = new CorporationRouting(this);
this.rerender(player);
}
rerender(player: IPlayer): void {
if (companyManagementDiv == null || corpRouting == null) {
if (companyManagementDiv == null) {
console.warn(
`Corporation.rerender() called when companyManagementDiv, corpRouting, or eventHandler is null`,
`Corporation.rerender() called when companyManagementDiv is null`,
);
return;
}
if (!routing.isOn(Page.Corporation)) return;
ReactDOM.render(
<CorporationRoot corp={this} routing={corpRouting} player={player} />,
<CorporationRoot corp={this} player={player} />,
companyManagementDiv,
);
}

@ -1,50 +1,67 @@
// React Components for the Corporation UI's City navigation tabs
// These allow player to navigate between different cities for each industry
import React from "react";
import React, { useState } from "react";
import { CityTab } from "./CityTab";
import { ExpandNewCityPopup } from "./ExpandNewCityPopup";
import { createPopup } from "../../ui/React/createPopup";
import { ICorporation } from "../ICorporation";
import { CorporationRouting } from "./Routing";
import { IIndustry } from "../IIndustry";
import { OfficeSpace } from "../OfficeSpace";
import { Industry } from "./Industry";
import { IPlayer } from "../../PersonObjects/IPlayer";
interface IProps {
routing: CorporationRouting;
onClicks: { [key: string]: () => void };
city: string; // currentCity
cityStateSetter: (city: string) => void;
city: string;
division: IIndustry;
corp: ICorporation;
player: IPlayer;
}
export function CityTabs(props: IProps): React.ReactElement {
const division = props.routing.currentDivision;
const [city, setCity] = useState(props.city);
function openExpandNewCityModal(): void {
if (division === null) return;
const popupId = "cmpy-mgmt-expand-city-popup";
createPopup(popupId, ExpandNewCityPopup, {
popupId: popupId,
corp: props.corp,
division: division,
cityStateSetter: props.cityStateSetter,
division: props.division,
cityStateSetter: setCity,
});
}
const office = props.division.offices[city];
if (office === 0) {
setCity("Sector-12");
return <></>;
}
return (
<>
{Object.keys(props.onClicks).map((cityName: string) => (
<CityTab
current={props.city === cityName}
key={cityName}
name={cityName}
onClick={props.onClicks[cityName]}
/>
))}
{Object.values(props.division.offices).map(
(office: OfficeSpace | 0) => office !== 0 && (
<CityTab
current={city === office.loc}
key={office.loc}
name={office.loc}
onClick={() => setCity(office.loc)}
/>
),
)}
<CityTab
current={false}
key={"Expand into new City"}
name={"Expand into new City"}
onClick={openExpandNewCityModal}
/>
<Industry
corp={props.corp}
division={props.division}
city={city}
warehouse={props.division.warehouses[city]}
office={office}
player={props.player}
/>
</>
);
}

@ -4,7 +4,6 @@ import { numeralWrapper } from "../../ui/numeralFormat";
import { CorporationConstants } from "../data/Constants";
import { removePopup } from "../../ui/React/createPopup";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { OfficeSpace } from "../OfficeSpace";
import { ICorporation } from "../ICorporation";
import { NewCity } from "../Actions";

@ -1,60 +1,60 @@
// React Components for the Corporation UI's navigation tabs
// These are the tabs at the top of the UI that let you switch to different
// divisions, see an overview of your corporation, or create a new industry
import React from "react";
import React, { useState } from "react";
import { HeaderTab } from "./HeaderTab";
import { IIndustry } from "../IIndustry";
import { NewIndustryPopup } from "./NewIndustryPopup";
import { createPopup } from "../../ui/React/createPopup";
import { ICorporation } from "../ICorporation";
import { CorporationRouting } from "./Routing";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { MainPanel } from "./MainPanel";
interface IProps {
corp: ICorporation;
routing: CorporationRouting;
player: IPlayer;
}
export function HeaderTabs(props: IProps): React.ReactElement {
function overviewOnClick(): void {
props.routing.routeToOverviewPage();
props.corp.rerender(props.player);
}
const [divisionName, setDivisionName] = useState("Overview");
function openNewIndustryPopup(): void {
const popupId = "cmpy-mgmt-expand-industry-popup";
createPopup(popupId, NewIndustryPopup, {
corp: props.corp,
routing: props.routing,
setDivisionName: setDivisionName,
popupId: popupId,
});
}
return (
<div>
<HeaderTab
current={props.routing.isOnOverviewPage()}
key={"overview"}
onClick={overviewOnClick}
text={props.corp.name}
/>
{props.corp.divisions.map((division: IIndustry) => (
<>
<div>
<HeaderTab
current={props.routing.isOn(division.name)}
key={division.name}
onClick={() => {
props.routing.routeTo(division.name);
props.corp.rerender(props.player);
}}
text={division.name}
current={divisionName === "Overview"}
key={"overview"}
onClick={() => setDivisionName("Overview")}
text={props.corp.name}
/>
))}
<HeaderTab
current={false}
onClick={openNewIndustryPopup}
text={"Expand into new Industry"}
{props.corp.divisions.map((division: IIndustry) => (
<HeaderTab
current={division.name === divisionName}
key={division.name}
onClick={() => setDivisionName(division.name)}
text={division.name}
/>
))}
<HeaderTab
current={false}
onClick={openNewIndustryPopup}
text={"Expand into new Industry"}
/>
</div>
<MainPanel
corp={props.corp}
divisionName={divisionName}
player={props.player}
/>
</div>
</>
);
}

@ -5,14 +5,18 @@ import React from "react";
import { IndustryOffice } from "./IndustryOffice";
import { IndustryOverview } from "./IndustryOverview";
import { IndustryWarehouse } from "./IndustryWarehouse";
import { Warehouse } from "../Warehouse";
import { ICorporation } from "../ICorporation";
import { CorporationRouting } from "./Routing";
import { OfficeSpace } from "../OfficeSpace";
import { IIndustry } from "../IIndustry";
import { IPlayer } from "../../PersonObjects/IPlayer";
interface IProps {
routing: CorporationRouting;
corp: ICorporation;
currentCity: string;
division: IIndustry;
city: string;
warehouse: Warehouse | 0;
office: OfficeSpace;
player: IPlayer;
}
@ -22,23 +26,25 @@ export function Industry(props: IProps): React.ReactElement {
<div className={"cmpy-mgmt-industry-left-panel"}>
<IndustryOverview
player={props.player}
routing={props.routing}
corp={props.corp}
currentCity={props.currentCity}
division={props.division}
currentCity={props.city}
office={props.office}
/>
<IndustryOffice
player={props.player}
routing={props.routing}
corp={props.corp}
currentCity={props.currentCity}
division={props.division}
office={props.office}
/>
</div>
<div className={"cmpy-mgmt-industry-right-panel"}>
<IndustryWarehouse
player={props.player}
corp={props.corp}
routing={props.routing}
currentCity={props.currentCity}
currentCity={props.city}
division={props.division}
warehouse={props.warehouse}
/>
</div>
</div>

@ -3,6 +3,7 @@
import React, { useState } from "react";
import { OfficeSpace } from "../OfficeSpace";
import { IIndustry } from "../IIndustry";
import { Employee } from "../Employee";
import { EmployeePositions } from "../EmployeePositions";
@ -15,20 +16,17 @@ import { HireEmployeePopup } from "./HireEmployeePopup";
import { ThrowPartyPopup } from "./ThrowPartyPopup";
import { ICorporation } from "../ICorporation";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { CorporationRouting } from "./Routing";
interface IProps {
routing: CorporationRouting;
corp: ICorporation;
currentCity: string;
division: IIndustry;
office: OfficeSpace;
player: IPlayer;
}
export function IndustryOffice(props: IProps): React.ReactElement {
const [employeeManualAssignMode, setEmployeeManualAssignMode] =
useState(false);
const [city, setCity] = useState("");
const [divisionName, setDivisionName] = useState("");
const [employee, setEmployee] = useState<Employee | null>(null);
const [numEmployees, setNumEmployees] = useState(0);
const [numOperations, setNumOperations] = useState(0);
@ -51,28 +49,8 @@ export function IndustryOffice(props: IProps): React.ReactElement {
}
function updateEmployeeCount(): void {
const division = props.routing.currentDivision;
if (division == null) {
throw new Error(
`Routing does not hold reference to the current Industry`,
);
}
const office = division.offices[props.currentCity];
if (!(office instanceof OfficeSpace)) {
throw new Error(
`Current City (${props.currentCity}) for UI does not have an OfficeSpace object`,
);
}
// If we're in a new city, we have to reset the state
if (division.name !== divisionName || props.currentCity !== city) {
resetEmployeeCount();
setDivisionName(division.name);
setCity(props.currentCity);
}
// Calculate how many NEW employees we need to account for
const currentNumEmployees = office.employees.length;
const currentNumEmployees = props.office.employees.length;
let newOperations = numOperations;
let newEngineers = numEngineers;
@ -83,8 +61,8 @@ export function IndustryOffice(props: IProps): React.ReactElement {
let newTraining = numTraining;
// Record the number of employees in each position, for NEW employees only
for (let i = numEmployees; i < office.employees.length; ++i) {
switch (office.employees[i].pos) {
for (let i = numEmployees; i < props.office.employees.length; ++i) {
switch (props.office.employees[i].pos) {
case EmployeePositions.Operations:
newOperations++;
break;
@ -108,7 +86,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
break;
default:
console.error(
"Unrecognized employee position: " + office.employees[i].pos,
"Unrecognized employee position: " + props.office.employees[i].pos,
);
break;
}
@ -139,10 +117,6 @@ export function IndustryOffice(props: IProps): React.ReactElement {
}
function renderAutomaticEmployeeManagement(): React.ReactElement {
const division = props.routing.currentDivision; // Validated in constructor
if (division === null) return <></>;
const office = division.offices[props.currentCity]; // Validated in constructor
if (office === 0) return <></>;
const vechain = props.corp.unlockUpgrades[4] === 1; // Has Vechain upgrade
function switchModeOnClick(): void {
@ -156,26 +130,24 @@ export function IndustryOffice(props: IProps): React.ReactElement {
totalHappiness = 0,
totalEnergy = 0,
totalSalary = 0;
for (let i = 0; i < office.employees.length; ++i) {
totalMorale += office.employees[i].mor;
totalHappiness += office.employees[i].hap;
totalEnergy += office.employees[i].ene;
totalSalary += office.employees[i].sal;
for (let i = 0; i < props.office.employees.length; ++i) {
totalMorale += props.office.employees[i].mor;
totalHappiness += props.office.employees[i].hap;
totalEnergy += props.office.employees[i].ene;
totalSalary += props.office.employees[i].sal;
}
let avgMorale = 0,
avgHappiness = 0,
avgEnergy = 0;
if (office.employees.length > 0) {
avgMorale = totalMorale / office.employees.length;
avgHappiness = totalHappiness / office.employees.length;
avgEnergy = totalEnergy / office.employees.length;
if (props.office.employees.length > 0) {
avgMorale = totalMorale / props.office.employees.length;
avgHappiness = totalHappiness / props.office.employees.length;
avgEnergy = totalEnergy / props.office.employees.length;
}
// Helper functions for (re-)assigning employees to different positions
function assignEmployee(to: string): void {
if (office === 0) return;
if (division === null) return;
if (numUnassigned <= 0) {
console.warn(
"Cannot assign employee. No unassigned employees available",
@ -211,14 +183,12 @@ export function IndustryOffice(props: IProps): React.ReactElement {
}
setNumUnassigned((n) => n - 1);
office.assignEmployeeToJob(to);
office.calculateEmployeeProductivity(props.corp, division);
props.office.assignEmployeeToJob(to);
props.office.calculateEmployeeProductivity(props.corp, props.division);
props.corp.rerender(props.player);
}
function unassignEmployee(from: string): void {
if (office === 0) return;
if (division === null) return;
function logWarning(pos: string): void {
console.warn(
`Cannot unassign from ${pos} because there is nobody assigned to that position`,
@ -271,8 +241,8 @@ export function IndustryOffice(props: IProps): React.ReactElement {
}
setNumUnassigned((n) => n + 1);
office.unassignEmployeeFromJob(from);
office.calculateEmployeeProductivity(props.corp, division);
props.office.unassignEmployeeFromJob(from);
props.office.calculateEmployeeProductivity(props.corp, props.division);
props.corp.rerender(props.player);
}
@ -375,7 +345,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
<p className={"tooltip"} style={{ display: "inline-block" }}>
Material Production:{" "}
{numeralWrapper.format(
division.getOfficeProductivity(office),
props.division.getOfficeProductivity(props.office),
"0.000",
)}
<span className={"tooltiptext"}>
@ -391,7 +361,9 @@ export function IndustryOffice(props: IProps): React.ReactElement {
<p className={"tooltip"} style={{ display: "inline-block" }}>
Product Production:{" "}
{numeralWrapper.format(
division.getOfficeProductivity(office, { forProduct: true }),
props.division.getOfficeProductivity(props.office, {
forProduct: true,
}),
"0.000",
)}
<span className={"tooltiptext"}>
@ -406,7 +378,10 @@ export function IndustryOffice(props: IProps): React.ReactElement {
{vechain && (
<p className={"tooltip"} style={{ display: "inline-block" }}>
Business Multiplier: x
{numeralWrapper.format(division.getBusinessFactor(office), "0.000")}
{numeralWrapper.format(
props.division.getBusinessFactor(props.office),
"0.000",
)}
<span className={"tooltiptext"}>
The effect this office's 'Business' employees has on boosting
sales
@ -542,12 +517,6 @@ export function IndustryOffice(props: IProps): React.ReactElement {
}
function renderManualEmployeeManagement(): React.ReactElement {
const corp = props.corp;
const division = props.routing.currentDivision; // Validated in constructor
if (division === null) return <></>;
const office = division.offices[props.currentCity]; // Validated in constructor
if (office === 0) return <></>;
function switchModeOnClick(): void {
setEmployeeManualAssignMode(false);
props.corp.rerender(props.player);
@ -561,10 +530,10 @@ export function IndustryOffice(props: IProps): React.ReactElement {
// Employee Selector
const employees = [];
for (let i = 0; i < office.employees.length; ++i) {
for (let i = 0; i < props.office.employees.length; ++i) {
employees.push(
<option key={office.employees[i].name}>
{office.employees[i].name}
<option key={props.office.employees[i].name}>
{props.office.employees[i].name}
</option>,
);
}
@ -572,16 +541,15 @@ export function IndustryOffice(props: IProps): React.ReactElement {
function employeeSelectorOnChange(
e: React.ChangeEvent<HTMLSelectElement>,
): void {
if (office === 0) return;
const name = getSelectText(e.target);
for (let i = 0; i < office.employees.length; ++i) {
if (name === office.employees[i].name) {
setEmployee(office.employees[i]);
for (let i = 0; i < props.office.employees.length; ++i) {
if (name === props.office.employees[i].name) {
setEmployee(props.office.employees[i]);
break;
}
}
corp.rerender(props.player);
props.corp.rerender(props.player);
}
// Employee Positions Selector
@ -607,7 +575,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
const pos = getSelectText(e.target);
employee.pos = pos;
resetEmployeeCount();
corp.rerender(props.player);
props.corp.rerender(props.player);
}
// Numeraljs formatter
@ -616,23 +584,23 @@ export function IndustryOffice(props: IProps): React.ReactElement {
// Employee stats (after applying multipliers)
const effCre = emp
? emp.cre *
corp.getEmployeeCreMultiplier() *
division.getEmployeeCreMultiplier()
props.corp.getEmployeeCreMultiplier() *
props.division.getEmployeeCreMultiplier()
: 0;
const effCha = emp
? emp.cha *
corp.getEmployeeChaMultiplier() *
division.getEmployeeChaMultiplier()
props.corp.getEmployeeChaMultiplier() *
props.division.getEmployeeChaMultiplier()
: 0;
const effInt = emp
? emp.int *
corp.getEmployeeIntMultiplier() *
division.getEmployeeIntMultiplier()
props.corp.getEmployeeIntMultiplier() *
props.division.getEmployeeIntMultiplier()
: 0;
const effEff = emp
? emp.eff *
corp.getEmployeeEffMultiplier() *
division.getEmployeeEffMultiplier()
props.corp.getEmployeeEffMultiplier() *
props.division.getEmployeeEffMultiplier()
: 0;
return (
@ -682,30 +650,25 @@ export function IndustryOffice(props: IProps): React.ReactElement {
);
}
const division = props.routing.currentDivision; // Validated in constructor
if (division === null) return <></>;
const office = division.offices[props.currentCity]; // Validated in constructor
if (office === 0) return <></>;
const buttonStyle = {
fontSize: "13px",
};
// Hire Employee button
let hireEmployeeButtonClass = "tooltip";
if (office.atCapacity()) {
if (props.office.atCapacity()) {
hireEmployeeButtonClass += " a-link-button-inactive";
} else {
hireEmployeeButtonClass += " std-button";
if (office.employees.length === 0) {
if (props.office.employees.length === 0) {
hireEmployeeButtonClass += " flashing-button";
}
}
function openHireEmployeePopup(): void {
if (office === 0) return;
const popupId = "cmpy-mgmt-hire-employee-popup";
createPopup(popupId, HireEmployeePopup, {
office: office,
office: props.office,
corp: props.corp,
popupId: popupId,
player: props.player,
@ -714,23 +677,21 @@ export function IndustryOffice(props: IProps): React.ReactElement {
// Autohire employee button
let autohireEmployeeButtonClass = "tooltip";
if (office.atCapacity()) {
if (props.office.atCapacity()) {
autohireEmployeeButtonClass += " a-link-button-inactive";
} else {
autohireEmployeeButtonClass += " std-button";
}
function autohireEmployeeButtonOnClick(): void {
if (office === 0) return;
if (office.atCapacity()) return;
office.hireRandomEmployee();
if (props.office.atCapacity()) return;
props.office.hireRandomEmployee();
props.corp.rerender(props.player);
}
function openUpgradeOfficeSizePopup(): void {
if (office === 0) return;
const popupId = "cmpy-mgmt-upgrade-office-size-popup";
createPopup(popupId, UpgradeOfficeSizePopup, {
office: office,
office: props.office,
corp: props.corp,
popupId: popupId,
player: props.player,
@ -738,10 +699,9 @@ export function IndustryOffice(props: IProps): React.ReactElement {
}
function openThrowPartyPopup(): void {
if (office === 0) return;
const popupId = "cmpy-mgmt-throw-office-party-popup";
createPopup(popupId, ThrowPartyPopup, {
office: office,
office: props.office,
corp: props.corp,
popupId: popupId,
});
@ -751,7 +711,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
<div className={"cmpy-mgmt-employee-panel"}>
<h1 style={{ margin: "4px 0px 5px 0px" }}>Office Space</h1>
<p>
Size: {office.employees.length} / {office.size} employees
Size: {props.office.employees.length} / {props.office.size} employees
</p>
<button
className={hireEmployeeButtonClass}
@ -759,7 +719,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
style={buttonStyle}
>
Hire Employee
{office.employees.length === 0 && (
{props.office.employees.length === 0 && (
<span className={"tooltiptext"}>
You'll need to hire some employees to get your operations started!
It's recommended to have at least one employee in every position
@ -787,7 +747,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
Upgrade the office's size so that it can hold more employees!
</span>
</button>
{!division.hasResearch("AutoPartyManager") && (
{!props.division.hasResearch("AutoPartyManager") && (
<button
className={"std-button tooltip"}
onClick={openThrowPartyPopup}

@ -5,6 +5,7 @@ import React from "react";
import { OfficeSpace } from "../OfficeSpace";
import { Industries } from "../IndustryData";
import { IndustryUpgrades } from "../IndustryUpgrades";
import { IIndustry } from "../IIndustry";
import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
@ -14,22 +15,20 @@ import { createPopup } from "../../ui/React/createPopup";
import { Money } from "../../ui/React/Money";
import { ICorporation } from "../ICorporation";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { CorporationRouting } from "./Routing";
interface IProps {
routing: CorporationRouting;
corp: ICorporation;
currentCity: string;
division: IIndustry;
office: OfficeSpace;
player: IPlayer;
}
export function IndustryOverview(props: IProps): React.ReactElement {
function renderMakeProductButton(): React.ReactElement {
const division = props.routing.currentDivision; // Validated inside render()
if (division === null) return <></>;
let createProductButtonText = "";
let createProductPopupText = "";
switch (division.type) {
switch (props.division.type) {
case Industries.Food:
createProductButtonText = "Build Restaurant";
createProductPopupText = "Build and manage a new restaurant!";
@ -80,7 +79,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
"the product. Investing money in its design will result in a superior product. " +
"Investing money in marketing the product will help the product's sales.";
const hasMaxProducts = division.hasMaximumNumberProducts();
const hasMaxProducts = props.division.hasMaximumNumberProducts();
const className = hasMaxProducts
? "a-link-button-inactive tooltip"
@ -91,11 +90,10 @@ export function IndustryOverview(props: IProps): React.ReactElement {
};
function openMakeProductPopup(): void {
if (division === null) return;
const popupId = "cmpy-mgmt-create-product-popup";
createPopup(popupId, MakeProductPopup, {
popupText: createProductPopupText,
division: division,
division: props.division,
corp: props.corp,
popupId: popupId,
});
@ -111,7 +109,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
{hasMaxProducts && (
<span className={"tooltiptext"}>
You have reached the maximum number of products:{" "}
{division.getMaximumNumberProducts()}
{props.division.getMaximumNumberProducts()}
</span>
)}
</button>
@ -119,16 +117,13 @@ export function IndustryOverview(props: IProps): React.ReactElement {
}
function renderText(): React.ReactElement {
const corp = props.corp;
const division = props.routing.currentDivision; // Validated inside render()
if (division === null) return <></>;
const vechain = corp.unlockUpgrades[4] === 1;
const profit = division.lastCycleRevenue
.minus(division.lastCycleExpenses)
const vechain = props.corp.unlockUpgrades[4] === 1;
const profit = props.division.lastCycleRevenue
.minus(props.division.lastCycleExpenses)
.toNumber();
let advertisingInfo = false;
const advertisingFactors = division.getAdvertisingFactors();
const advertisingFactors = props.division.getAdvertisingFactors();
const awarenessFac = advertisingFactors[1];
const popularityFac = advertisingFactors[2];
const ratioFac = advertisingFactors[3];
@ -138,7 +133,6 @@ export function IndustryOverview(props: IProps): React.ReactElement {
}
function productionMultHelpTipOnClick(): void {
if (division === null) return;
// Wrapper for createProgressBarText()
// Converts the industry's "effectiveness factors"
// into a graphic (string) depicting how high that effectiveness is
@ -163,34 +157,41 @@ export function IndustryOverview(props: IProps): React.ReactElement {
"Below are approximations for how effective each material is at boosting " +
"this industry's production multiplier (Bigger bars = more effective):<br><br>" +
`Hardware:&nbsp;&nbsp;&nbsp; ${convertEffectFacToGraphic(
division.hwFac,
props.division.hwFac,
)}<br>` +
`Robots:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ${convertEffectFacToGraphic(
division.robFac,
props.division.robFac,
)}<br>` +
`AI Cores:&nbsp;&nbsp;&nbsp; ${convertEffectFacToGraphic(
division.aiFac,
props.division.aiFac,
)}<br>` +
`Real Estate: ${convertEffectFacToGraphic(division.reFac)}`,
`Real Estate: ${convertEffectFacToGraphic(props.division.reFac)}`,
);
}
function openResearchPopup(): void {
if (division === null) return;
const popupId = "corporation-research-popup-box";
createPopup(popupId, ResearchPopup, {
industry: division,
industry: props.division,
popupId: popupId,
});
}
return (
<div>
Industry: {division.type} (Corp Funds:{" "}
<Money money={corp.funds.toNumber()} />)
Industry: {props.division.type} (Corp Funds:{" "}
<Money money={props.corp.funds.toNumber()} />)
<br /> <br />
Awareness: {numeralWrapper.format(division.awareness, "0.000")} <br />
Popularity: {numeralWrapper.format(division.popularity, "0.000")} <br />
Awareness: {numeralWrapper.format(
props.division.awareness,
"0.000",
)}{" "}
<br />
Popularity: {numeralWrapper.format(
props.division.popularity,
"0.000",
)}{" "}
<br />
{advertisingInfo !== false && (
<p className={"tooltip"}>
Advertising Multiplier: x
@ -213,16 +214,17 @@ export function IndustryOverview(props: IProps): React.ReactElement {
{advertisingInfo}
<br />
<br />
Revenue: <Money money={division.lastCycleRevenue.toNumber()} /> / s{" "}
<br />
Revenue: <Money money={props.division.lastCycleRevenue.toNumber()} /> /
s <br />
Expenses: <Money
money={division.lastCycleExpenses.toNumber()}
/> /s <br />
money={props.division.lastCycleExpenses.toNumber()}
/>{" "}
/s <br />
Profit: <Money money={profit} /> / s
<br /> <br />
<p className={"tooltip"}>
Production Multiplier:{" "}
{numeralWrapper.format(division.prodMult, "0.00")}
{numeralWrapper.format(props.division.prodMult, "0.00")}
<span className={"tooltiptext"}>
Production gain from owning production-boosting materials such as
hardware, Robots, AI Cores, and Real Estate
@ -234,7 +236,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
<br /> <br />
<p className={"tooltip"}>
Scientific Research:{" "}
{numeralWrapper.format(division.sciResearch.qty, "0.000a")}
{numeralWrapper.format(props.division.sciResearch.qty, "0.000a")}
<span className={"tooltiptext"}>
Scientific Research increases the quality of the materials and
products that you produce.
@ -248,22 +250,12 @@ export function IndustryOverview(props: IProps): React.ReactElement {
}
function renderUpgrades(): React.ReactElement[] {
const corp = props.corp;
const division = props.routing.currentDivision; // Validated inside render()
if (division === null) return [<></>];
const office = division.offices[props.currentCity];
if (!(office instanceof OfficeSpace)) {
throw new Error(
`Current City (${props.currentCity}) for UI does not have an OfficeSpace object`,
);
}
const upgrades = [];
for (const index in IndustryUpgrades) {
const upgrade = IndustryUpgrades[index];
// AutoBrew research disables the Coffee upgrade
if (division.hasResearch("AutoBrew") && upgrade[4] === "Coffee") {
if (props.division.hasResearch("AutoBrew") && upgrade[4] === "Coffee") {
continue;
}
@ -273,26 +265,24 @@ export function IndustryOverview(props: IProps): React.ReactElement {
let cost = 0;
switch (i) {
case 0: //Coffee, cost is static per employee
cost = office.employees.length * baseCost;
cost = props.office.employees.length * baseCost;
break;
default:
cost = baseCost * Math.pow(priceMult, division.upgrades[i]);
cost = baseCost * Math.pow(priceMult, props.division.upgrades[i]);
break;
}
function onClick(): void {
if (office === 0) return;
if (division === null) return;
if (corp.funds.lt(cost)) {
if (props.corp.funds.lt(cost)) {
dialogBoxCreate("Insufficient funds");
} else {
corp.funds = corp.funds.minus(cost);
division.upgrade(upgrade, {
corporation: corp,
office: office,
props.corp.funds = props.corp.funds.minus(cost);
props.division.upgrade(upgrade, {
corporation: props.corp,
office: props.office,
});
// corp.displayDivisionContent(division, city);
corp.rerender(props.player);
props.corp.rerender(props.player);
}
}
@ -335,11 +325,6 @@ export function IndustryOverview(props: IProps): React.ReactElement {
);
}
const division = props.routing.currentDivision;
if (division == null) {
throw new Error(`Routing does not hold reference to the current Industry`);
}
const makeProductButton = renderMakeProductButton();
return (
@ -351,7 +336,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
</u>
<br />
{renderUpgrades()} <br />
{division.makesProducts && makeProductButton}
{props.division.makesProducts && makeProductButton}
</div>
);
}

@ -23,7 +23,6 @@ import { createPopup } from "../../ui/React/createPopup";
import { isString } from "../../../utils/helpers/isString";
import { ICorporation } from "../ICorporation";
import { IIndustry } from "../IIndustry";
import { CorporationRouting } from "./Routing";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { SetSmartSupply } from "../Actions";
@ -438,7 +437,8 @@ function MaterialComponent(props: IMaterialProps): React.ReactElement {
interface IProps {
corp: ICorporation;
routing: CorporationRouting;
division: IIndustry;
warehouse: Warehouse | 0;
currentCity: string;
player: IPlayer;
}
@ -464,53 +464,49 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
}
function renderWarehouseUI(): React.ReactElement {
const corp = props.corp;
const division = props.routing.currentDivision; // Validated in render()
if (division === null) return <></>;
const warehouse = division.warehouses[props.currentCity]; // Validated in render()
if (warehouse === 0) return <></>;
if (props.warehouse === 0) return <></>;
// General Storage information at the top
const sizeUsageStyle = {
color: warehouse.sizeUsed >= warehouse.size ? "red" : "white",
color: props.warehouse.sizeUsed >= props.warehouse.size ? "red" : "white",
margin: "5px",
};
// Upgrade Warehouse size button
const sizeUpgradeCost =
CorporationConstants.WarehouseUpgradeBaseCost *
Math.pow(1.07, warehouse.level + 1);
const canAffordUpgrade = corp.funds.gt(sizeUpgradeCost);
Math.pow(1.07, props.warehouse.level + 1);
const canAffordUpgrade = props.corp.funds.gt(sizeUpgradeCost);
const upgradeWarehouseClass = canAffordUpgrade
? "std-button"
: "a-link-button-inactive";
function upgradeWarehouseOnClick(): void {
if (division === null) return;
if (warehouse === 0) return;
++warehouse.level;
warehouse.updateSize(corp, division);
corp.funds = corp.funds.minus(sizeUpgradeCost);
corp.rerender(props.player);
if (props.division === null) return;
if (props.warehouse === 0) return;
++props.warehouse.level;
props.warehouse.updateSize(props.corp, props.division);
props.corp.funds = props.corp.funds.minus(sizeUpgradeCost);
props.corp.rerender(props.player);
}
// Industry material Requirements
let generalReqsText =
"This Industry uses [" +
Object.keys(division.reqMats).join(", ") +
Object.keys(props.division.reqMats).join(", ") +
"] in order to ";
if (division.prodMats.length > 0) {
generalReqsText += "produce [" + division.prodMats.join(", ") + "] ";
if (division.makesProducts) {
generalReqsText += " and " + division.getProductDescriptionText();
if (props.division.prodMats.length > 0) {
generalReqsText +=
"produce [" + props.division.prodMats.join(", ") + "] ";
if (props.division.makesProducts) {
generalReqsText += " and " + props.division.getProductDescriptionText();
}
} else if (division.makesProducts) {
generalReqsText += division.getProductDescriptionText() + ".";
} else if (props.division.makesProducts) {
generalReqsText += props.division.getProductDescriptionText() + ".";
}
const ratioLines = [];
for (const matName in division.reqMats) {
if (division.reqMats.hasOwnProperty(matName)) {
const text = [" *", division.reqMats[matName], matName].join(" ");
for (const matName in props.division.reqMats) {
if (props.division.reqMats.hasOwnProperty(matName)) {
const text = [" *", props.division.reqMats[matName], matName].join(" ");
ratioLines.push(
<div key={matName}>
<p>{text}</p>
@ -520,19 +516,21 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
}
let createdItemsText = "in order to create ";
if (division.prodMats.length > 0) {
if (props.division.prodMats.length > 0) {
createdItemsText +=
"one of each produced Material (" + division.prodMats.join(", ") + ") ";
if (division.makesProducts) {
"one of each produced Material (" +
props.division.prodMats.join(", ") +
") ";
if (props.division.makesProducts) {
createdItemsText += "or to create one of its Products";
}
} else if (division.makesProducts) {
} else if (props.division.makesProducts) {
createdItemsText += "one of its Products";
}
// Current State:
let stateText;
switch (division.state) {
switch (props.division.state) {
case "START":
stateText = "Current state: Preparing...";
break;
@ -549,32 +547,32 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
stateText = "Current state: Exporting materials and/or products...";
break;
default:
console.error(`Invalid state: ${division.state}`);
console.error(`Invalid state: ${props.division.state}`);
break;
}
// Smart Supply Checkbox
const smartSupplyCheckboxId = "cmpy-mgmt-smart-supply-checkbox";
function smartSupplyOnChange(e: React.ChangeEvent<HTMLInputElement>): void {
if (warehouse === 0) return;
SetSmartSupply(warehouse, e.target.checked);
corp.rerender(props.player);
if (props.warehouse === 0) return;
SetSmartSupply(props.warehouse, e.target.checked);
props.corp.rerender(props.player);
}
// Create React components for materials
const mats = [];
for (const matName in warehouse.materials) {
if (warehouse.materials[matName] instanceof Material) {
for (const matName in props.warehouse.materials) {
if (props.warehouse.materials[matName] instanceof Material) {
// Only create UI for materials that are relevant for the industry
if (isRelevantMaterial(matName, division)) {
if (isRelevantMaterial(matName, props.division)) {
mats.push(
<MaterialComponent
city={props.currentCity}
corp={corp}
division={division}
corp={props.corp}
division={props.division}
key={matName}
mat={warehouse.materials[matName]}
warehouse={warehouse}
mat={props.warehouse.materials[matName]}
warehouse={props.warehouse}
/>,
);
}
@ -583,16 +581,19 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
// Create React components for products
const products = [];
if (division.makesProducts && Object.keys(division.products).length > 0) {
for (const productName in division.products) {
const product = division.products[productName];
if (
props.division.makesProducts &&
Object.keys(props.division.products).length > 0
) {
for (const productName in props.division.products) {
const product = props.division.products[productName];
if (product instanceof Product) {
products.push(
<ProductComponent
player={props.player}
city={props.currentCity}
corp={corp}
division={division}
corp={props.corp}
division={props.division}
key={productName}
product={product}
/>,
@ -604,11 +605,11 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
return (
<div className={"cmpy-mgmt-warehouse-panel"}>
<p className={"tooltip"} style={sizeUsageStyle}>
Storage: {numeralWrapper.formatBigNumber(warehouse.sizeUsed)} /{" "}
{numeralWrapper.formatBigNumber(warehouse.size)}
Storage: {numeralWrapper.formatBigNumber(props.warehouse.sizeUsed)} /{" "}
{numeralWrapper.formatBigNumber(props.warehouse.size)}
<span
className={"tooltiptext"}
dangerouslySetInnerHTML={{ __html: warehouse.breakdown }}
dangerouslySetInnerHTML={{ __html: props.warehouse.breakdown }}
></span>
</p>
@ -632,7 +633,7 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
<p>{stateText}</p>
{corp.unlockUpgrades[1] && (
{props.corp.unlockUpgrades[1] && (
<div>
<label style={{ color: "white" }} htmlFor={smartSupplyCheckboxId}>
Enable Smart Supply
@ -642,7 +643,7 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
id={smartSupplyCheckboxId}
onChange={smartSupplyOnChange}
style={{ margin: "3px" }}
checked={warehouse.smartSupplyEnabled}
checked={props.warehouse.smartSupplyEnabled}
/>
</div>
)}
@ -654,12 +655,6 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
);
}
const division = props.routing.currentDivision;
if (division == null) {
throw new Error(`Routing does not hold reference to the current Industry`);
}
const warehouse = division.warehouses[props.currentCity];
function purchaseWarehouse(division: IIndustry, city: string): void {
if (props.corp.funds.lt(CorporationConstants.WarehouseInitialCost)) {
dialogBoxCreate("You do not have enough funds to do this!");
@ -677,14 +672,14 @@ export function IndustryWarehouse(props: IProps): React.ReactElement {
}
}
if (warehouse instanceof Warehouse) {
if (props.warehouse instanceof Warehouse) {
return renderWarehouseUI();
} else {
return (
<div className={"cmpy-mgmt-warehouse-panel"}>
<button
className={"std-button"}
onClick={() => purchaseWarehouse(division, props.currentCity)}
onClick={() => purchaseWarehouse(props.division, props.currentCity)}
>
Purchase Warehouse (
{numeralWrapper.formatMoney(

@ -1,7 +1,6 @@
// React components for the levelable upgrade buttons on the overview panel
import React from "react";
import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { ICorporation } from "../ICorporation";
import { IPlayer } from "../../PersonObjects/IPlayer";

@ -1,100 +1,46 @@
// React Component for the element that contains the actual info/data
// for the Corporation UI. This panel lies below the header tabs and will
// be filled with whatever is needed based on the routing/navigation
import React, { useState } from "react";
import React from "react";
import { CityTabs } from "./CityTabs";
import { Industry } from "./Industry";
import { IIndustry } from "../IIndustry";
import { Overview } from "./Overview";
import { OfficeSpace } from "../OfficeSpace";
import { CityName } from "../../Locations/data/CityNames";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { ICorporation } from "../ICorporation";
import { CorporationRouting } from "./Routing";
interface IProps {
corp: ICorporation;
routing: CorporationRouting;
player: IPlayer;
divisionName: string;
}
export function MainPanel(props: IProps): React.ReactElement {
const [division, setDivision] = useState("");
const [city, setCity] = useState<string>(CityName.Sector12);
const division =
props.divisionName !== "Overview"
? props.corp.divisions.find(
(division: IIndustry) => division.name === props.divisionName,
)
: undefined; // use undefined because find returns undefined
// We can pass this setter to child components
function changeCityState(newCity: string): void {
if (Object.values(CityName).includes(newCity as CityName)) {
setCity(newCity);
} else {
console.error(
`Tried to change MainPanel's city state to an invalid city: ${newCity}`,
);
}
}
function renderOverviewPage(): React.ReactElement {
if (division === undefined) {
return (
<div id="cmpy-mgmt-panel">
<Overview {...props} />
</div>
);
}
function renderDivisionPage(): React.ReactElement {
// Note: Division is the same thing as Industry...I wasn't consistent with naming
const division = props.routing.currentDivision;
if (division == null) {
throw new Error(
`Routing does not hold reference to the current Industry`,
);
}
// City tabs
const onClicks: { [key: string]: () => void } = {};
for (const cityName in division.offices) {
if (division.offices[cityName] instanceof OfficeSpace) {
onClicks[cityName] = () => {
setCity(cityName);
props.corp.rerender(props.player);
};
}
}
const cityTabs = (
<CityTabs
{...props}
corp={props.corp}
city={city}
onClicks={onClicks}
cityStateSetter={changeCityState}
/>
);
} else {
return (
<div id="cmpy-mgmt-panel">
{cityTabs}
<Industry {...props} currentCity={city} />
<CityTabs
division={division}
corp={props.corp}
city={CityName.Sector12}
player={props.player}
/>
</div>
);
}
if (props.routing.isOnOverviewPage()) {
// Corporation overview Content
return renderOverviewPage();
} else {
// Division content
// First, check if we're at a new division. If so, we need to reset the city to Sector-12
// Otherwise, just switch the 'city' state
const currentDivision = props.routing.current();
if (currentDivision !== division) {
setDivision(currentDivision);
setCity(CityName.Sector12);
}
return renderDivisionPage();
}
}

@ -1,21 +1,15 @@
import React, { useState } from "react";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { removePopup } from "../../ui/React/createPopup";
import {
Industries,
IndustryStartingCosts,
IndustryDescriptions,
} from "../IndustryData";
import { Industry } from "../Industry";
import { Industries, IndustryDescriptions } from "../IndustryData";
import { ICorporation } from "../ICorporation";
import { IIndustry } from "../IIndustry";
import { CorporationRouting } from "./Routing";
import { NewIndustry } from "../Actions";
interface IProps {
corp: ICorporation;
popupId: string;
routing: CorporationRouting;
setDivisionName: (name: string) => void;
}
// Create a popup that lets the player create a new industry.
// This is created when the player clicks the "Expand into new Industry" header tab
@ -23,8 +17,7 @@ export function NewIndustryPopup(props: IProps): React.ReactElement {
const allIndustries = Object.keys(Industries).sort();
const possibleIndustries = allIndustries
.filter(
(industryType: string) =>
props.corp.divisions.find(
(industryType: string) => props.corp.divisions.find(
(division: IIndustry) => division.type === industryType,
) === undefined,
)
@ -43,7 +36,7 @@ export function NewIndustryPopup(props: IProps): React.ReactElement {
}
// Set routing to the new division so that the UI automatically switches to it
props.routing.routeTo(name);
props.setDivisionName(name);
removePopup(props.popupId);
}

@ -33,10 +33,6 @@ interface IProps {
player: IPlayer;
}
interface GeneralBtns {
bribeFactions: React.ReactElement;
}
export function Overview(props: IProps): React.ReactElement {
// Generic Function for Creating a button
interface ICreateButtonProps {
@ -64,26 +60,6 @@ export function Overview(props: IProps): React.ReactElement {
);
}
function createButton(props: ICreateButtonProps): React.ReactElement {
let className = props.class ? props.class : "std-button";
const displayStyle = props.display ? props.display : "block";
const hasTooltip = props.tooltip != null;
if (hasTooltip) {
className += " tooltip";
}
return (
<a
className={className}
onClick={props.onClick}
style={{ display: displayStyle }}
>
{props.text}
{hasTooltip && <span className={"tooltiptext"}>{props.tooltip}</span>}
</a>
);
}
function openBribeFactionPopup(): void {
const popupId = "corp-bribe-popup";
createPopup(popupId, BribeFactionPopup, {
@ -97,7 +73,7 @@ export function Overview(props: IProps): React.ReactElement {
.minus(props.corp.expenses)
.toNumber();
function DividendsStats() {
function DividendsStats(): React.ReactElement {
if (props.corp.dividendPercentage <= 0 || profit <= 0) return <></>;
const totalDividends = (props.corp.dividendPercentage / 100) * profit;
const retainedEarnings = profit - totalDividends;
@ -330,8 +306,7 @@ export function Overview(props: IProps): React.ReactElement {
<h1 className={"cmpy-mgmt-upgrade-header"}> Unlocks </h1>
{Object.values(CorporationUnlockUpgrades)
.filter(
(upgrade: CorporationUnlockUpgrade) =>
props.corp.unlockUpgrades[upgrade[0]] === 0,
(upgrade: CorporationUnlockUpgrade) => props.corp.unlockUpgrades[upgrade[0]] === 0,
)
.map((upgrade: CorporationUnlockUpgrade) => (
<UnlockUpgrade

@ -2,30 +2,18 @@
import React from "react";
import { HeaderTabs } from "./HeaderTabs";
import { MainPanel } from "./MainPanel";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { ICorporation } from "../ICorporation";
import { CorporationRouting } from "./Routing";
interface IProps {
corp: ICorporation;
routing: CorporationRouting;
player: IPlayer;
}
export function CorporationRoot(props: IProps): React.ReactElement {
return (
<div>
<HeaderTabs
corp={props.corp}
routing={props.routing}
player={props.player}
/>
<MainPanel
corp={props.corp}
routing={props.routing}
player={props.player}
/>
<HeaderTabs corp={props.corp} player={props.player} />
</div>
);
}

@ -1,90 +0,0 @@
import { ICorporation } from "../ICorporation";
import { IIndustry } from "../IIndustry";
export const overviewPage = "Overview";
/**
* Keeps track of what content is currently being displayed for the Corporation UI
*/
export class CorporationRouting {
private currentPage: string = overviewPage;
// Stores a reference to the Corporation instance
private corp: ICorporation;
// Stores a reference to the Division instance that the routing is currently on
// This will be null if routing is on the overview page
currentDivision: IIndustry | null = null;
constructor(corp: ICorporation) {
this.corp = corp;
}
current(): string {
return this.currentPage;
}
/**
* Checks that the specified page has a valid value
*/
isValidPage(page: string): boolean {
if (page === overviewPage) {
return true;
}
for (const division of this.corp.divisions) {
if (division.name === page) {
return true;
}
}
return false;
}
/**
* Returns a boolean indicating whether or not the player is on the given page
*/
isOn(page: string): boolean {
if (!this.isValidPage(page)) {
return false;
}
return page === this.currentPage;
}
isOnOverviewPage(): boolean {
return this.currentPage === overviewPage;
}
/**
* Routes to the specified page
*/
routeTo(page: string): void {
if (!this.isValidPage(page)) {
return;
}
this.currentDivision = null;
if (page !== overviewPage) {
// Iterate through Corporation data to get a reference to the current division
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
// the overview page or a division page
if (this.currentDivision == null) {
console.warn(`Routing could not find division ${page}`);
}
}
this.currentPage = page;
}
routeToOverviewPage(): void {
this.currentPage = overviewPage;
this.currentDivision = null;
}
}

@ -1,7 +1,6 @@
import React, { useState } from "react";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { removePopup } from "../../ui/React/createPopup";
import { Cities } from "../../Locations/Cities";
import { Product } from "../Product";
import { SellProduct } from "../Actions";

@ -1,7 +1,6 @@
// React Components for the Unlock upgrade buttons on the overview page
import React from "react";
import { numeralWrapper } from "../../ui/numeralFormat";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { CorporationUnlockUpgrade } from "../data/CorporationUnlockUpgrades";
import { ICorporation } from "../ICorporation";

@ -746,8 +746,7 @@ class DevMenuComponent extends Component {
}
let sourceFiles = [];
validSFN.forEach((i) =>
sourceFiles.push(
validSFN.forEach((i) => sourceFiles.push(
<tr key={"sf-" + i}>
<td>
<span className="text">SF-{i}:</span>

@ -1,7 +1,5 @@
import React from "react";
import { AllServers } from "../Server/AllServers";
import { Script } from "../Script/Script";
import { TextFile } from "../TextFile";
import { Accordion } from "../ui/React/Accordion";
import { numeralWrapper } from "../ui/numeralFormat";
@ -61,9 +59,7 @@ export function ServerAccordion(props: IServerProps): React.ReactElement {
);
}
interface IProps {}
export function FileDiagnosticPopup(props: IProps): React.ReactElement {
export function FileDiagnosticPopup(): React.ReactElement {
const ips: string[] = [];
for (const ip of Object.keys(AllServers)) {
ips.push(ip);

@ -1,4 +1,3 @@
import { CONSTANTS } from "../Constants";
import { FactionInfo, FactionInfos } from "./FactionInfo";
import { favorToRep, repToFavor } from "./formulas/favor";
import {

@ -124,8 +124,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
render(): React.ReactNode {
const augs = this.getAugsSorted();
const purchasable = augs.filter(
(aug: string) =>
aug === AugmentationNames.NeuroFluxGovernor ||
(aug: string) => aug === AugmentationNames.NeuroFluxGovernor ||
(!this.props.p.augmentations.some((a) => a.name === aug) &&
!this.props.p.queuedAugmentations.some((a) => a.name === aug)),
);
@ -142,8 +141,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
);
};
const augListElems = purchasable.map((aug) =>
purchaseableAugmentation(aug),
const augListElems = purchasable.map((aug) => purchaseableAugmentation(aug),
);
let ownedElem = <></>;
@ -172,20 +170,17 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
will enhance your abilities.
</p>
<StdButton
onClick={() =>
this.switchSortOrder(PurchaseAugmentationsOrderSetting.Cost)
onClick={() => this.switchSortOrder(PurchaseAugmentationsOrderSetting.Cost)
}
text={"Sort by Cost"}
/>
<StdButton
onClick={() =>
this.switchSortOrder(PurchaseAugmentationsOrderSetting.Reputation)
onClick={() => this.switchSortOrder(PurchaseAugmentationsOrderSetting.Reputation)
}
text={"Sort by Reputation"}
/>
<StdButton
onClick={() =>
this.switchSortOrder(PurchaseAugmentationsOrderSetting.Default)
onClick={() => this.switchSortOrder(PurchaseAugmentationsOrderSetting.Default)
}
text={"Sort by Default Order"}
/>

@ -31,8 +31,6 @@ const inputStyleMarkup = {
height: "26px",
};
const blockStyle = { display: "block" };
export function DonateOption(props: IProps): React.ReactElement {
const [donateAmt, setDonateAmt] = useState<number | null>(null);
const digits = (CONSTANTS.DonateMoneyToRepDivisor + "").length - 1;

@ -33,8 +33,7 @@ export function GangMemberList(props: IProps): React.ReactElement {
}
const members = props.gang.members.filter(
(member: GangMember) =>
member.name.indexOf(filter) > -1 || member.task.indexOf(filter) > -1,
(member: GangMember) => member.name.indexOf(filter) > -1 || member.task.indexOf(filter) > -1,
);
return (

@ -90,8 +90,7 @@ export function TerritorySubpage(props: IProps): React.ReactElement {
id="warfare"
type="checkbox"
style={{ display: "inline-block", margin: "2px" }}
onChange={(event) =>
(props.gang.territoryWarfareEngaged = event.target.checked)
onChange={(event) => (props.gang.territoryWarfareEngaged = event.target.checked)
}
/>
<label
@ -125,8 +124,7 @@ export function TerritorySubpage(props: IProps): React.ReactElement {
id="notify"
type="checkbox"
style={{ display: "inline-block", margin: "2px" }}
onChange={(event) =>
(props.gang.notifyMemberDeath = event.target.checked)
onChange={(event) => (props.gang.notifyMemberDeath = event.target.checked)
}
/>
<label

@ -11,7 +11,6 @@ import { AddToAllServers, createUniqueRandomIp } from "../Server/AllServers";
import { safetlyCreateUniqueServer } from "../Server/ServerHelpers";
import {
getPurchaseServerCost,
purchaseRamForHomeComputer,
purchaseServer,
} from "../Server/ServerPurchases";
import { SpecialServerIps } from "../Server/SpecialServerIps";

@ -1,15 +1,6 @@
import React, { useState } from "react";
import { Location } from "../Location";
import {
createPurchaseServerPopup,
createUpgradeHomeCoresPopup,
purchaseTorRouter,
} from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
import { StdButtonPurchased } from "../../ui/React/StdButtonPurchased";
import { StdButton } from "../../ui/React/StdButton";
@ -48,23 +39,6 @@ export function CoresButton(props: IProps): React.ReactElement {
homeComputer.cpuCores++;
rerender();
}
const settings = {
CommonHTML: {
scale: 90,
},
"HTML-CSS": {
scale: 90,
},
NativeMML: {
scale: 90,
},
SVG: {
scale: 90,
},
PreviewHTML: {
scale: 90,
},
};
return (
<StdButton

@ -1,12 +1,5 @@
import React, { useState } from "react";
import { Location } from "../Location";
import {
createPurchaseServerPopup,
createUpgradeHomeCoresPopup,
purchaseTorRouter,
} from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";

@ -6,20 +6,14 @@
import * as React from "react";
import { Location } from "../Location";
import {
createPurchaseServerPopup,
createUpgradeHomeCoresPopup,
purchaseTorRouter,
} from "../LocationsHelpers";
import { createPurchaseServerPopup } from "../LocationsHelpers";
import { RamButton } from "./RamButton";
import { TorButton } from "./TorButton";
import { CoresButton } from "./CoresButton";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { getPurchaseServerCost } from "../../Server/ServerPurchases";
import { StdButtonPurchased } from "../../ui/React/StdButtonPurchased";
import { StdButton } from "../../ui/React/StdButton";
import { Money } from "../../ui/React/Money";

@ -1,15 +1,9 @@
import React, { useState } from "react";
import { Location } from "../Location";
import {
createPurchaseServerPopup,
createUpgradeHomeCoresPopup,
purchaseTorRouter,
} from "../LocationsHelpers";
import { purchaseTorRouter } from "../LocationsHelpers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
import { StdButtonPurchased } from "../../ui/React/StdButtonPurchased";
import { StdButton } from "../../ui/React/StdButton";

@ -149,8 +149,7 @@ export const RamCosts: IMap<any> = {
purchase4SMarketData: () => RamCostConstants.ScriptBuySellStockRamCost,
purchase4SMarketDataTixApi: () => RamCostConstants.ScriptBuySellStockRamCost,
getPurchasedServerLimit: () => RamCostConstants.ScriptGetPurchasedServerLimit,
getPurchasedServerMaxRam: () =>
RamCostConstants.ScriptGetPurchasedServerMaxRam,
getPurchasedServerMaxRam: () => RamCostConstants.ScriptGetPurchasedServerMaxRam,
getPurchasedServerCost: () => RamCostConstants.ScriptGetPurchaseServerRamCost,
purchaseServer: () => RamCostConstants.ScriptPurchaseServerRamCost,
deleteServer: () => RamCostConstants.ScriptPurchaseServerRamCost,
@ -189,8 +188,7 @@ export const RamCosts: IMap<any> = {
manualHack: () => RamCostConstants.ScriptSingularityFn1RamCost,
installBackdoor: () => RamCostConstants.ScriptSingularityFn1RamCost,
getStats: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
getCharacterInformation: () =>
RamCostConstants.ScriptSingularityFn1RamCost / 4,
getCharacterInformation: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
getPlayer: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
hospitalize: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
isBusy: () => RamCostConstants.ScriptSingularityFn1RamCost / 4,
@ -215,8 +213,7 @@ export const RamCosts: IMap<any> = {
getCrimeStats: () => RamCostConstants.ScriptSingularityFn3RamCost,
getOwnedAugmentations: () => RamCostConstants.ScriptSingularityFn3RamCost,
getOwnedSourceFiles: () => RamCostConstants.ScriptSingularityFn3RamCost,
getAugmentationsFromFaction: () =>
RamCostConstants.ScriptSingularityFn3RamCost,
getAugmentationsFromFaction: () => RamCostConstants.ScriptSingularityFn3RamCost,
getAugmentationPrereq: () => RamCostConstants.ScriptSingularityFn3RamCost,
getAugmentationCost: () => RamCostConstants.ScriptSingularityFn3RamCost,
getAugmentationStats: () => RamCostConstants.ScriptSingularityFn3RamCost,
@ -230,8 +227,7 @@ export const RamCosts: IMap<any> = {
inGang: () => RamCostConstants.ScriptGangApiBaseRamCost / 4,
getMemberNames: () => RamCostConstants.ScriptGangApiBaseRamCost / 4,
getGangInformation: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,
getOtherGangInformation: () =>
RamCostConstants.ScriptGangApiBaseRamCost / 2,
getOtherGangInformation: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,
getMemberInformation: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,
canRecruitMember: () => RamCostConstants.ScriptGangApiBaseRamCost / 4,
recruitMember: () => RamCostConstants.ScriptGangApiBaseRamCost / 2,
@ -251,30 +247,21 @@ export const RamCosts: IMap<any> = {
// Bladeburner API
bladeburner: {
getContractNames: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getOperationNames: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getBlackOpNames: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getContractNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getOperationNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getBlackOpNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getBlackOpRank: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 2,
getGeneralActionNames: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getGeneralActionNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
getSkillNames: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 10,
startAction: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
stopBladeburnerAction: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost / 2,
getCurrentAction: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost / 4,
stopBladeburnerAction: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 2,
getCurrentAction: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost / 4,
getActionTime: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getActionEstimatedSuccessChance: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getActionEstimatedSuccessChance: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getActionRepGain: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getActionCountRemaining: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getActionCountRemaining: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getActionMaxLevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getActionCurrentLevel: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getActionCurrentLevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getActionAutolevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
setActionAutolevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
setActionLevel: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
@ -285,18 +272,14 @@ export const RamCosts: IMap<any> = {
upgradeSkill: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getTeamSize: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
setTeamSize: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getCityEstimatedPopulation: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getCityEstimatedCommunities: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getCityEstimatedPopulation: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getCityEstimatedCommunities: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getCityChaos: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getCity: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
switchCity: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getStamina: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
joinBladeburnerFaction: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost,
joinBladeburnerDivision: () =>
RamCostConstants.ScriptBladeburnerApiBaseRamCost,
joinBladeburnerFaction: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
joinBladeburnerDivision: () => RamCostConstants.ScriptBladeburnerApiBaseRamCost,
getBonusTime: () => 0,
},
@ -306,8 +289,7 @@ export const RamCosts: IMap<any> = {
getContractType: () => RamCostConstants.ScriptCodingContractBaseRamCost / 2,
getData: () => RamCostConstants.ScriptCodingContractBaseRamCost / 2,
getDescription: () => RamCostConstants.ScriptCodingContractBaseRamCost / 2,
getNumTriesRemaining: () =>
RamCostConstants.ScriptCodingContractBaseRamCost / 5,
getNumTriesRemaining: () => RamCostConstants.ScriptCodingContractBaseRamCost / 5,
},
// Duplicate Sleeve API

@ -29,8 +29,7 @@ export async function executeJSScript(scripts = [], workerScript) {
script.markUpdated();
urls = _getScriptUrls(script, scripts, []);
script.url = urls[urls.length - 1].url;
script.module = new Promise((resolve) =>
resolve(eval("import(urls[urls.length - 1].url)")),
script.module = new Promise((resolve) => resolve(eval("import(urls[urls.length - 1].url)")),
);
script.dependencies = urls;
}

@ -125,8 +125,7 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
// Finally, walk the reference map and generate a ram cost. The initial set of keys to scan
// are those that start with __SPECIAL_INITIAL_MODULE__.
let ram = RamCostConstants.ScriptBaseRamCost;
const unresolvedRefs = Object.keys(dependencyMap).filter((s) =>
s.startsWith(initialModule),
const unresolvedRefs = Object.keys(dependencyMap).filter((s) => s.startsWith(initialModule),
);
const resolvedRefs = new Set();
while (unresolvedRefs.length > 0) {
@ -148,8 +147,7 @@ async function parseOnlyRamCalculate(otherScripts, code, workerScript) {
if (ref.endsWith(".*")) {
// A prefix reference. We need to find all matching identifiers.
const prefix = ref.slice(0, ref.length - 2);
for (let ident of Object.keys(dependencyMap).filter((k) =>
k.startsWith(prefix),
for (let ident of Object.keys(dependencyMap).filter((k) => k.startsWith(prefix),
)) {
for (let dep of dependencyMap[ident] || []) {
if (!resolvedRefs.has(dep)) unresolvedRefs.push(dep);

@ -1,32 +1,11 @@
import { Script } from "./Script";
import { RamCalculationErrorCode } from "./RamCalculationErrorCodes";
import { calculateRamUsage } from "./RamCalculations";
import { isScriptFilename } from "./ScriptHelpersTS";
import { CONSTANTS } from "../Constants";
import { Engine } from "../engine";
import { parseFconfSettings } from "../Fconf/Fconf";
import {
iTutorialSteps,
iTutorialNextStep,
ITutorial,
} from "../InteractiveTutorial";
import { Player } from "../Player";
import { CursorPositions } from "../ScriptEditor/CursorPositions";
import { AllServers } from "../Server/AllServers";
import { processSingleServerGrowth } from "../Server/ServerHelpers";
import { Settings } from "../Settings/Settings";
import { EditorSetting } from "../Settings/SettingEnums";
import { isValidFilePath } from "../Terminal/DirectoryHelpers";
import { TextFile } from "../TextFile";
import { Page, routing } from "../ui/navigationTracking";
import { numeralWrapper } from "../ui/numeralFormat";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { compareArrays } from "../../utils/helpers/compareArrays";
import { createElement } from "../../utils/uiHelpers/createElement";
export function scriptCalculateOfflineProduction(runningScriptObj) {
//The Player object stores the last update time from when we were online

@ -13,7 +13,7 @@ export function OptionsPopup(props: IProps): React.ReactElement {
const [theme, setTheme] = useState(props.options.theme);
const [insertSpaces, setInsertSpaces] = useState(props.options.insertSpaces);
function save() {
function save(): void {
props.save({
theme: theme,
insertSpaces: insertSpaces,

@ -23,7 +23,6 @@ import { libSource } from "../NetscriptDefinitions";
import { NetscriptFunctions } from "../../NetscriptFunctions";
import { WorkerScript } from "../../Netscript/WorkerScript";
import { Settings } from "../../Settings/Settings";
import { GetServerByHostname } from "../../Server/ServerHelpers";
import {
iTutorialNextStep,
ITutorial,
@ -287,7 +286,7 @@ export function Root(props: IProps): React.ReactElement {
}, [code]);
useEffect(() => {
function maybeSave(event: KeyboardEvent) {
function maybeSave(event: KeyboardEvent): void {
if (Settings.DisableHotkeys) return;
//Ctrl + b
if (event.keyCode == 66 && (event.ctrlKey || event.metaKey)) {

@ -130,8 +130,7 @@ export function initForeignServers(homeComputer: Server): void {
server2.serversOnNetwork.push(server1.ip);
};
const getRandomArrayItem = (arr: any[]): any =>
arr[Math.floor(Math.random() * arr.length)];
const getRandomArrayItem = (arr: any[]): any => arr[Math.floor(Math.random() * arr.length)];
const linkNetworkLayers = (
network1: Server[],
@ -145,8 +144,7 @@ export function initForeignServers(homeComputer: Server): void {
// Connect the first tier of servers to the player's home computer
linkNetworkLayers(networkLayers[0], () => homeComputer);
for (let i = 1; i < networkLayers.length; i++) {
linkNetworkLayers(networkLayers[i], () =>
getRandomArrayItem(networkLayers[i - 1]),
linkNetworkLayers(networkLayers[i], () => getRandomArrayItem(networkLayers[i - 1]),
);
}
}

@ -1,9 +1,5 @@
import { ISelfInitializer, ISelfLoading } from "../types";
import {
AceKeybindingSetting,
CodeMirrorKeybindingSetting,
CodeMirrorThemeSetting,
EditorSetting,
OwnedAugmentationsOrderSetting,
PurchaseAugmentationsOrderSetting,
} from "./SettingEnums";

@ -97,7 +97,6 @@ import * as JSZip from "jszip";
import * as FileSaver from "file-saver";
import * as libarg from "arg";
import React from "react";
import ReactDOM from "react-dom";
function postNetburnerText() {
post("Bitburner v" + CONSTANTS.Version);
@ -1166,8 +1165,7 @@ let Terminal = {
const server = Player.getCurrentServer();
if (
!server.scripts.some((script) =>
script.filename.startsWith(evaledDir),
!server.scripts.some((script) => script.filename.startsWith(evaledDir),
) &&
!server.textFiles.some((file) => file.fn.startsWith(evaledDir))
) {

@ -1,5 +1,6 @@
import { setTimeoutRef } from "./utils/SetTimeoutRef";
import { dialogBoxCreate } from "../utils/DialogBox";
import { BaseServer } from "./Server/BaseServer";
import {
Generic_fromJSON,
Generic_toJSON,
@ -103,7 +104,7 @@ Reviver.constructors.TextFile = TextFile;
* @returns The file object, or null if it couldn't find it.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export function getTextFile(fn: string, server: any): TextFile | null {
export function getTextFile(fn: string, server: BaseServer): TextFile | null {
const filename: string = !fn.endsWith(".txt") ? `${fn}.txt` : fn;
for (const file of server.textFiles as TextFile[]) {
@ -126,7 +127,7 @@ export function getTextFile(fn: string, server: any): TextFile | null {
export function createTextFile(
fn: string,
txt: string,
server: any,
server: BaseServer,
): TextFile | undefined {
if (getTextFile(fn, server) !== null) {
// This should probably be a `throw`...

@ -158,8 +158,7 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
d += "&nbsp;&nbsp;&nbsp;&nbsp;[\n";
d += n
.map(
(line: number[]) =>
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[" +
(line: number[]) => "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[" +
line.map((x: number) => `${x}`.padStart(2, " ")).join(",") +
"]",
)

@ -53,7 +53,6 @@ import {
loadAllRunningScripts,
updateOnlineScriptTimes,
} from "./NetscriptWorker";
import { GetServerByHostname } from "./Server/ServerHelpers";
import { Player } from "./Player";
import { prestigeAugmentation } from "./Prestige";
import {

@ -4,7 +4,6 @@
*/
import * as React from "react";
import { WorkerScriptAccordion } from "./WorkerScriptAccordion";
import { Accordion } from "../React/Accordion";
import { ServerAccordionContent } from "./ServerAccordionContent";
@ -33,12 +32,6 @@ export function ServerAccordion(props: IProps): React.ReactElement {
};
const headerTxt = `${paddedName} ${createProgressBarText(barOptions)}`;
const scripts = props.workerScripts.map((ws) => {
return (
<WorkerScriptAccordion key={`${ws.name}_${ws.args}`} workerScript={ws} />
);
});
return (
<Accordion
headerContent={<pre>{headerTxt}</pre>}

@ -9,8 +9,7 @@ interface IProps {
}
function randomize(char: string): string {
const randFrom = (str: string): string =>
str[Math.floor(Math.random() * str.length)];
const randFrom = (str: string): string => str[Math.floor(Math.random() * str.length)];
const classes = [
"abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",

@ -48,7 +48,7 @@ function ScriptLogPopup(props: IProps): React.ReactElement {
}
useEffect(() => {
function closeHandler(event: KeyboardEvent) {
function closeHandler(event: KeyboardEvent): void {
if (event.keyCode === 27) {
close();
}