From 50f14b4f581c9021809bc9e39fb8a4ab12bc1e86 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Mon, 3 Oct 2022 12:12:16 -0400 Subject: [PATCH 1/8] Commit1 --- src/Achievements/Achievements.ts | 5 +- src/Alias.ts | 5 +- src/Augmentation/StaticAugmentations.ts | 3 +- src/BitNode/BitNode.tsx | 3 +- src/Bladeburner/BlackOperations.tsx | 3 +- src/Bladeburner/GeneralActions.tsx | 3 +- src/Bladeburner/Skills.ts | 3 +- src/CodingContracts.ts | 4 +- src/Company/Companies.ts | 3 +- src/Company/Company.ts | 6 +- src/Company/CompanyPositions.ts | 3 +- src/Company/data/CompaniesMetadata.ts | 39 +- src/Corporation/Actions.ts | 8 +- src/Corporation/EmployeePositions.ts | 6 +- src/Corporation/MaterialSizes.ts | 4 +- src/Corporation/Product.ts | 13 +- src/Corporation/ProductRatingWeights.ts | 3 +- src/Corporation/ResearchMap.ts | 3 +- src/Corporation/ResearchTree.ts | 4 +- src/Corporation/Warehouse.ts | 3 +- src/Crime/Crimes.ts | 3 +- src/DarkWeb/DarkWebItems.ts | 3 +- src/DevMenu/ui/SaveFile.tsx | 4 +- src/Electron.tsx | 12 +- src/Faction/FactionInfo.tsx | 3 +- src/Faction/Factions.ts | 4 +- src/GameOptions/ui/GameOptionsSidebar.tsx | 6 +- src/Hacknet/HashManager.ts | 3 +- src/Hacknet/HashUpgrades.ts | 3 +- src/Literature/Literatures.ts | 3 +- src/Literature/data/LiteratureNames.ts | 6 +- src/Locations/Cities.ts | 3 +- src/Locations/Locations.ts | 4 +- src/Locations/createCityMap.ts | 5 +- src/Locations/ui/SpecialLocation.tsx | 4 +- src/Netscript/RamCostGenerator.ts | 5 +- src/Netscript/WorkerScript.ts | 7 +- src/NetscriptFunctions.ts | 24 +- src/NetscriptFunctions/Corporation.ts | 5 +- src/NetscriptFunctions/Infiltration.ts | 4 +- src/NetscriptFunctions/Sleeve.ts | 4 +- src/PersonObjects/Player/PlayerObject.ts | 3 +- .../Player/PlayerObjectGeneralMethods.ts | 8 +- src/Programs/Programs.ts | 3 +- src/RemoteFileAPI/Remote.ts | 8 +- src/SaveObject.tsx | 12 +- src/Script/RunningScript.ts | 3 +- src/ScriptEditor/NetscriptDefinitions.d.ts | 24 +- src/Server/AllServers.ts | 4 +- src/Settings/Settings.ts | 361 ++++-------------- src/SourceFile/SourceFiles.tsx | 3 +- src/StockMarket/OrderProcessing.tsx | 4 +- src/StockMarket/StockMarket.tsx | 6 +- src/StockMarket/data/StockSymbols.ts | 75 ++-- .../data/TickerHeaderFormatData.ts | 2 +- src/Terminal/HelpText.ts | 5 +- src/Terminal/commands/cat.ts | 4 +- src/Themes/Themes.ts | 3 +- src/Themes/ui/ThemeBrowser.tsx | 4 +- src/Themes/ui/ThemeEditorModal.tsx | 68 ++-- src/engine.tsx | 4 +- src/types.ts | 35 +- src/ui/React/Snackbar.tsx | 9 +- src/utils/StringHelperFunctions.ts | 3 +- src/utils/helpers/checkEnum.ts | 6 - src/utils/helpers/checkObjContains.ts | 7 + test/jest/StockMarket.test.ts | 3 +- 67 files changed, 307 insertions(+), 599 deletions(-) delete mode 100644 src/utils/helpers/checkEnum.ts create mode 100644 src/utils/helpers/checkObjContains.ts diff --git a/src/Achievements/Achievements.ts b/src/Achievements/Achievements.ts index acbf35dd8..fa6a33e79 100644 --- a/src/Achievements/Achievements.ts +++ b/src/Achievements/Achievements.ts @@ -20,7 +20,6 @@ import { SpecialServers } from "../Server/data/SpecialServers"; import { Server } from "../Server/Server"; import { Router } from "../ui/GameRoot"; import { Page } from "../ui/Router"; -import { IMap } from "../types"; import * as data from "./AchievementData.json"; import { FactionNames } from "../Faction/data/FactionNames"; import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames"; @@ -47,7 +46,7 @@ export interface PlayerAchievement { } export interface AchievementDataJson { - achievements: IMap; + achievements: Record; } export interface AchievementData { @@ -87,7 +86,7 @@ function sfAchievement(): Achievement[] { return achs; } -export const achievements: IMap = { +export const achievements: Record = { [FactionNames.CyberSec.toUpperCase()]: { ...achievementData[FactionNames.CyberSec.toUpperCase()], Icon: "CSEC", diff --git a/src/Alias.ts b/src/Alias.ts index ee2801564..aa65642a1 100644 --- a/src/Alias.ts +++ b/src/Alias.ts @@ -1,8 +1,7 @@ -import { IMap } from "./types"; import { Terminal } from "./Terminal"; -export let Aliases: IMap = {}; -export let GlobalAliases: IMap = {}; +export let Aliases: Record = {}; +export let GlobalAliases: Record = {}; export function loadAliases(saveString: string): void { if (saveString === "") { diff --git a/src/Augmentation/StaticAugmentations.ts b/src/Augmentation/StaticAugmentations.ts index 768e52770..68ea0046a 100644 --- a/src/Augmentation/StaticAugmentations.ts +++ b/src/Augmentation/StaticAugmentations.ts @@ -1,4 +1,3 @@ import { Augmentation } from "./Augmentation"; -import { IMap } from "../types"; -export const StaticAugmentations: IMap = {}; +export const StaticAugmentations: Record = {}; diff --git a/src/BitNode/BitNode.tsx b/src/BitNode/BitNode.tsx index 2abb4eea6..ade41b3e0 100644 --- a/src/BitNode/BitNode.tsx +++ b/src/BitNode/BitNode.tsx @@ -1,7 +1,6 @@ import React from "react"; import { Player } from "../Player"; import { BitNodeMultipliers, IBitNodeMultipliers } from "./BitNodeMultipliers"; -import { IMap } from "../types"; import { FactionNames } from "../Faction/data/FactionNames"; import { CityName } from "../Locations/data/CityNames"; @@ -29,7 +28,7 @@ class BitNode { } } -export const BitNodes: IMap = {}; +export const BitNodes: Record = {}; export function initBitNodes() { BitNodes["BitNode1"] = new BitNode( 1, diff --git a/src/Bladeburner/BlackOperations.tsx b/src/Bladeburner/BlackOperations.tsx index 588543c23..b369ce2f6 100644 --- a/src/Bladeburner/BlackOperations.tsx +++ b/src/Bladeburner/BlackOperations.tsx @@ -1,8 +1,7 @@ import { BlackOperation } from "./BlackOperation"; -import { IMap } from "../types"; import { BlackOperationNames } from "./data/BlackOperationNames"; -export const BlackOperations: IMap = {}; +export const BlackOperations: Record = {}; (function () { BlackOperations[BlackOperationNames.OperationTyphoon] = new BlackOperation({ diff --git a/src/Bladeburner/GeneralActions.tsx b/src/Bladeburner/GeneralActions.tsx index dfe5b3d8e..d41973ed6 100644 --- a/src/Bladeburner/GeneralActions.tsx +++ b/src/Bladeburner/GeneralActions.tsx @@ -1,7 +1,6 @@ import { Action } from "./Action"; -import { IMap } from "../types"; -export const GeneralActions: IMap = {}; +export const GeneralActions: Record = {}; const actionNames: Array = [ "Training", diff --git a/src/Bladeburner/Skills.ts b/src/Bladeburner/Skills.ts index a8bc0810c..df56154d2 100644 --- a/src/Bladeburner/Skills.ts +++ b/src/Bladeburner/Skills.ts @@ -1,8 +1,7 @@ import { Skill } from "./Skill"; import { SkillNames } from "./data/SkillNames"; -import { IMap } from "../types"; -export const Skills: IMap = {}; +export const Skills: Record = {}; (function () { Skills[SkillNames.BladesIntuition] = new Skill({ diff --git a/src/CodingContracts.ts b/src/CodingContracts.ts index 0ffa743aa..caf8cba1d 100644 --- a/src/CodingContracts.ts +++ b/src/CodingContracts.ts @@ -1,7 +1,5 @@ import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, SolverFunc } from "./data/codingcontracttypes"; -import { IMap } from "./types"; - import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "./utils/JSONReviver"; import { CodingContractEvent } from "./ui/React/CodingContractModal"; @@ -58,7 +56,7 @@ class CodingContractType { /* Contract Types */ // tslint:disable-next-line -export const CodingContractTypes: IMap = {}; +export const CodingContractTypes: Record = {}; for (const md of codingContractTypesMetadata) { // tslint:disable-next-line diff --git a/src/Company/Companies.ts b/src/Company/Companies.ts index 7ad6d9d39..37721fc81 100644 --- a/src/Company/Companies.ts +++ b/src/Company/Companies.ts @@ -1,10 +1,9 @@ // Constructs all CompanyPosition objects using the metadata in data/companypositions.ts import { companiesMetadata } from "./data/CompaniesMetadata"; import { Company, IConstructorParams } from "./Company"; -import { IMap } from "../types"; import { Reviver } from "../utils/JSONReviver"; -export let Companies: IMap = {}; +export let Companies: Record = {}; function addCompany(params: IConstructorParams): void { if (Companies[params.name] != null) { diff --git a/src/Company/Company.ts b/src/Company/Company.ts index 492ed4ad3..70081eaf3 100644 --- a/src/Company/Company.ts +++ b/src/Company/Company.ts @@ -2,14 +2,12 @@ import { CompanyPosition } from "./CompanyPosition"; import * as posNames from "./data/companypositionnames"; import { favorToRep, repToFavor } from "../Faction/formulas/favor"; -import { IMap } from "../types"; - import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; export interface IConstructorParams { name: string; info: string; - companyPositions: IMap; + companyPositions: Record; expMultiplier: number; salaryMultiplier: number; jobStatReqOffset: number; @@ -48,7 +46,7 @@ export class Company { * * Must match names of Company Positions, defined in data/companypositionnames.ts */ - companyPositions: IMap; + companyPositions: Record; /** * Company-specific multiplier for earnings diff --git a/src/Company/CompanyPositions.ts b/src/Company/CompanyPositions.ts index 3075808a4..b4147e116 100644 --- a/src/Company/CompanyPositions.ts +++ b/src/Company/CompanyPositions.ts @@ -1,9 +1,8 @@ // Constructs all CompanyPosition objects using the metadata in data/companypositions.ts import { companyPositionMetadata } from "./data/CompanyPositionsMetadata"; import { CompanyPosition, IConstructorParams } from "./CompanyPosition"; -import { IMap } from "../types"; -export const CompanyPositions: IMap = {}; +export const CompanyPositions: Record = {}; function addCompanyPosition(params: IConstructorParams): void { if (CompanyPositions[params.name] != null) { diff --git a/src/Company/data/CompaniesMetadata.ts b/src/Company/data/CompaniesMetadata.ts index 74acb3d6b..85af9e2ca 100644 --- a/src/Company/data/CompaniesMetadata.ts +++ b/src/Company/data/CompaniesMetadata.ts @@ -1,30 +1,29 @@ import * as posNames from "./companypositionnames"; import { IConstructorParams } from "../Company"; -import { IMap } from "../../types"; import { LocationName } from "../../Locations/data/LocationNames"; // Create Objects containing Company Positions by category // Will help in metadata construction later -const AllSoftwarePositions: IMap = {}; -const AllITPositions: IMap = {}; -const AllNetworkEngineerPositions: IMap = {}; -const SecurityEngineerPositions: IMap = {}; -const AllTechnologyPositions: IMap = {}; -const AllBusinessPositions: IMap = {}; -const AllAgentPositions: IMap = {}; -const AllSecurityPositions: IMap = {}; -const AllSoftwareConsultantPositions: IMap = {}; -const AllBusinessConsultantPositions: IMap = {}; -const SoftwarePositionsUpToHeadOfEngineering: IMap = {}; -const SoftwarePositionsUpToLeadDeveloper: IMap = {}; -const BusinessPositionsUpToOperationsManager: IMap = {}; -const WaiterOnly: IMap = {}; -const EmployeeOnly: IMap = {}; -const PartTimeWaiterOnly: IMap = {}; -const PartTimeEmployeeOnly: IMap = {}; -const OperationsManagerOnly: IMap = {}; -const CEOOnly: IMap = {}; +const AllSoftwarePositions: Record = {}; +const AllITPositions: Record = {}; +const AllNetworkEngineerPositions: Record = {}; +const SecurityEngineerPositions: Record = {}; +const AllTechnologyPositions: Record = {}; +const AllBusinessPositions: Record = {}; +const AllAgentPositions: Record = {}; +const AllSecurityPositions: Record = {}; +const AllSoftwareConsultantPositions: Record = {}; +const AllBusinessConsultantPositions: Record = {}; +const SoftwarePositionsUpToHeadOfEngineering: Record = {}; +const SoftwarePositionsUpToLeadDeveloper: Record = {}; +const BusinessPositionsUpToOperationsManager: Record = {}; +const WaiterOnly: Record = {}; +const EmployeeOnly: Record = {}; +const PartTimeWaiterOnly: Record = {}; +const PartTimeEmployeeOnly: Record = {}; +const OperationsManagerOnly: Record = {}; +const CEOOnly: Record = {}; posNames.SoftwareCompanyPositions.forEach((e) => { AllSoftwarePositions[e] = true; diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index 3b65654a7..5cdfc5e9f 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -14,6 +14,7 @@ import { Cities } from "../Locations/Cities"; import { EmployeePositions } from "./EmployeePositions"; import { ResearchMap } from "./ResearchMap"; import { isRelevantMaterial } from "./ui/Helpers"; +import { checkObjContainsValue } from "../utils/helpers/checkObjContains"; export function NewIndustry(corporation: Corporation, industry: string, name: string): void { if (corporation.divisions.find(({ type }) => industry == type)) @@ -303,16 +304,13 @@ export function BuyBackShares(corporation: Corporation, numShares: number): bool export function AssignJob(office: OfficeSpace, employeeName: string, job: string): void { const employee = office.employees.find((e) => e.name === employeeName); - if (!employee) throw new Error(`Could not find employee '${name}'.`); - if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); - + if (!checkObjContainsValue(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`) office.assignSingleJob(employee, job); } export function AutoAssignJob(office: OfficeSpace, job: string, count: number): boolean { - if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); - + if (!checkObjContainsValue(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`) return office.autoAssignJob(job, count); } diff --git a/src/Corporation/EmployeePositions.ts b/src/Corporation/EmployeePositions.ts index ed7d524cd..e560314c6 100644 --- a/src/Corporation/EmployeePositions.ts +++ b/src/Corporation/EmployeePositions.ts @@ -1,6 +1,4 @@ -import { IMap } from "../types"; - -export const EmployeePositions: IMap = { +export const EmployeePositions = { Operations: "Operations", Engineer: "Engineer", Business: "Business", @@ -8,4 +6,4 @@ export const EmployeePositions: IMap = { RandD: "Research & Development", Training: "Training", Unassigned: "Unassigned", -}; +} as const; diff --git a/src/Corporation/MaterialSizes.ts b/src/Corporation/MaterialSizes.ts index 74a19cb7e..b7e402a54 100644 --- a/src/Corporation/MaterialSizes.ts +++ b/src/Corporation/MaterialSizes.ts @@ -1,7 +1,5 @@ -import { IMap } from "../types"; - // Map of material (by name) to their sizes (how much space it takes in warehouse) -export const MaterialSizes: IMap = { +export const MaterialSizes: Record = { Water: 0.05, Energy: 0.01, Food: 0.03, diff --git a/src/Corporation/Product.ts b/src/Corporation/Product.ts index e85380372..1700f683f 100644 --- a/src/Corporation/Product.ts +++ b/src/Corporation/Product.ts @@ -4,7 +4,6 @@ import { Industry } from "./Industry"; import { ProductRatingWeights, IProductRatingWeight } from "./ProductRatingWeights"; import { createCityMap } from "../Locations/createCityMap"; -import { IMap } from "../types"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; import { getRandomInt } from "../utils/helpers/getRandomInt"; @@ -25,7 +24,7 @@ interface IConstructorParams { features?: number; loc?: string; size?: number; - req?: IMap; + req?: Record; } export class Product { @@ -81,7 +80,7 @@ export class Product { // Data refers to the production, sale, and quantity of the products // These values are specific to a city // For each city, the data is [qty, prod, sell] - data: IMap = createCityMap([0, 0, 0]); + data: Record = createCityMap([0, 0, 0]); // Location of this Product // Only applies for location-based products like restaurants/hospitals @@ -93,18 +92,18 @@ export class Product { // Material requirements. An object that maps the name of a material to how much it requires // to make 1 unit of the product. - reqMats: IMap = {}; + reqMats: Record = {}; // Data to keep track of whether production/sale of this Product is // manually limited. These values are specific to a city // [Whether production/sale is limited, limit amount] - prdman: IMap = createCityMap([false, 0]); - sllman: IMap = createCityMap([false, 0]); + prdman: Record = createCityMap([false, 0]); + sllman: Record = createCityMap([false, 0]); // Flags that signal whether automatic sale pricing through Market TA is enabled marketTa1 = false; marketTa2 = false; - marketTa2Price: IMap = createCityMap(0); + marketTa2Price: Record = createCityMap(0); // Determines the maximum amount of this product that can be sold in one market cycle maxsll = 0; diff --git a/src/Corporation/ProductRatingWeights.ts b/src/Corporation/ProductRatingWeights.ts index 667a59f0b..01997180f 100644 --- a/src/Corporation/ProductRatingWeights.ts +++ b/src/Corporation/ProductRatingWeights.ts @@ -1,5 +1,4 @@ import { Industries } from "./IndustryData"; -import { IMap } from "../types"; export interface IProductRatingWeight { Aesthetics?: number; @@ -10,7 +9,7 @@ export interface IProductRatingWeight { Reliability?: number; } -export const ProductRatingWeights: IMap = { +export const ProductRatingWeights: Record = { [Industries.Food]: { Quality: 0.7, Durability: 0.1, diff --git a/src/Corporation/ResearchMap.ts b/src/Corporation/ResearchMap.ts index 7b2ab3928..606faf3d7 100644 --- a/src/Corporation/ResearchMap.ts +++ b/src/Corporation/ResearchMap.ts @@ -2,9 +2,8 @@ // as values. They are identified by their names import { Research, IConstructorParams } from "./Research"; import { researchMetadata } from "./data/ResearchMetadata"; -import { IMap } from "../types"; -export const ResearchMap: IMap = {}; +export const ResearchMap: Record = {}; function addResearch(p: IConstructorParams): void { if (ResearchMap[p.name] != null) { diff --git a/src/Corporation/ResearchTree.ts b/src/Corporation/ResearchTree.ts index a76d2aaa1..82313d107 100644 --- a/src/Corporation/ResearchTree.ts +++ b/src/Corporation/ResearchTree.ts @@ -6,8 +6,6 @@ import { Research } from "./Research"; import { ResearchMap } from "./ResearchMap"; -import { IMap } from "../types"; - interface IConstructorParams { children?: Node[]; cost: number; @@ -86,7 +84,7 @@ export class Node { // The root node in a Research Tree must always be the "Hi-Tech R&D Laboratory" export class ResearchTree { // Object containing names of all acquired Research by name - researched: IMap = {}; + researched: Record = {}; // Root Node root: Node | null = null; diff --git a/src/Corporation/Warehouse.ts b/src/Corporation/Warehouse.ts index 874651399..8edbe3cfa 100644 --- a/src/Corporation/Warehouse.ts +++ b/src/Corporation/Warehouse.ts @@ -2,7 +2,6 @@ import { Material } from "./Material"; import { Corporation } from "./Corporation"; import { Industry } from "./Industry"; import { MaterialSizes } from "./MaterialSizes"; -import { IMap } from "../types"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; import { exceptionAlert } from "../utils/helpers/exceptionAlert"; @@ -21,7 +20,7 @@ export class Warehouse { loc: string; // Map of Materials held by this Warehouse - materials: IMap; + materials: Record; // Maximum amount warehouse can hold size: number; diff --git a/src/Crime/Crimes.ts b/src/Crime/Crimes.ts index d1f24b646..b3cf29060 100644 --- a/src/Crime/Crimes.ts +++ b/src/Crime/Crimes.ts @@ -1,11 +1,10 @@ import { Crime } from "./Crime"; import { CONSTANTS } from "../Constants"; -import { IMap } from "../types"; import { CrimeType } from "../utils/WorkType"; -export const Crimes: IMap = { +export const Crimes: Record = { Shoplift: new Crime("Shoplift", "to shoplift", CrimeType.SHOPLIFT, 2e3, 15e3, 1 / 20, 0.1, { dexterity_success_weight: 1, agility_success_weight: 1, diff --git a/src/DarkWeb/DarkWebItems.ts b/src/DarkWeb/DarkWebItems.ts index 191540fbf..1af0c4226 100644 --- a/src/DarkWeb/DarkWebItems.ts +++ b/src/DarkWeb/DarkWebItems.ts @@ -1,8 +1,7 @@ import { DarkWebItem } from "./DarkWebItem"; -import { IMap } from "../types"; import { Programs, initPrograms } from "../Programs/Programs"; -export const DarkWebItems: IMap = {}; +export const DarkWebItems: Record = {}; export function initDarkWebItems() { initPrograms(); Object.assign(DarkWebItems, { diff --git a/src/DevMenu/ui/SaveFile.tsx b/src/DevMenu/ui/SaveFile.tsx index 8f7d9003b..0d2ff3391 100644 --- a/src/DevMenu/ui/SaveFile.tsx +++ b/src/DevMenu/ui/SaveFile.tsx @@ -7,7 +7,7 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import { saveObject } from "../../SaveObject"; -import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; +import { SnackbarEvents } from "../../ui/React/Snackbar"; import { Upload } from "@mui/icons-material"; import { Button } from "@mui/material"; import { OptionSwitch } from "../../ui/React/OptionSwitch"; @@ -25,7 +25,7 @@ export function SaveFile(): React.ReactElement { const save = atob(base64Save); setSaveFile(save); } catch (e: unknown) { - SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000); + SnackbarEvents.emit(String(e), "error", 5000); } } diff --git a/src/Electron.tsx b/src/Electron.tsx index a07621afc..89d61112c 100644 --- a/src/Electron.tsx +++ b/src/Electron.tsx @@ -3,7 +3,7 @@ import { Router } from "./ui/GameRoot"; import { removeLeadingSlash } from "./Terminal/DirectoryHelpers"; import { Terminal } from "./Terminal"; import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; -import { IMap, IReturnStatus } from "./types"; +import { IReturnStatus } from "./types"; import { GetServer } from "./Server/AllServers"; import { ImportPlayerData, SaveData, saveObject } from "./SaveObject"; import { Settings } from "./Settings/Settings"; @@ -125,7 +125,7 @@ function initWebserver(): void { function initAppNotifier(): void { const funcs = { terminal: (message: string, type?: string) => { - const typesFn: IMap<(s: string) => void> = { + const typesFn: Record void> = { info: Terminal.info, warn: Terminal.warn, error: Terminal.error, @@ -151,7 +151,7 @@ function initSaveFunctions(): void { saveObject.exportGame(); } catch (error) { console.error(error); - SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000); + SnackbarEvents.emit("Could not export game.", "error", 2000); } }, triggerScriptsExport: (): void => exportScripts("*", Player.getHomeComputer()), @@ -203,7 +203,7 @@ function initElectronBridge(): void { }) .catch((error: unknown) => { console.error(error); - SnackbarEvents.emit("Could not save game.", ToastVariant.ERROR, 2000); + SnackbarEvents.emit("Could not save game.", "error", 2000); }); }); bridge.receive("trigger-game-export", () => { @@ -211,7 +211,7 @@ function initElectronBridge(): void { window.appSaveFns.triggerGameExport(); } catch (error) { console.error(error); - SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000); + SnackbarEvents.emit("Could not export game.", "error", 2000); } }); bridge.receive("trigger-scripts-export", () => { @@ -219,7 +219,7 @@ function initElectronBridge(): void { window.appSaveFns.triggerScriptsExport(); } catch (error) { console.error(error); - SnackbarEvents.emit("Could not export scripts.", ToastVariant.ERROR, 2000); + SnackbarEvents.emit("Could not export scripts.", "error", 2000); } }); } diff --git a/src/Faction/FactionInfo.tsx b/src/Faction/FactionInfo.tsx index 0a63d868d..1dfd62b5a 100644 --- a/src/Faction/FactionInfo.tsx +++ b/src/Faction/FactionInfo.tsx @@ -1,5 +1,4 @@ import React from "react"; -import { IMap } from "../types"; import { FactionNames } from "./data/FactionNames"; import { Router } from "../ui/GameRoot"; import { Option } from "./ui/Option"; @@ -81,7 +80,7 @@ export class FactionInfo { * A map of all factions and associated info to them. */ // tslint:disable-next-line:variable-name -export const FactionInfos: IMap = { +export const FactionInfos: Record = { // Endgame [FactionNames.Illuminati]: new FactionInfo({ infoText: ( diff --git a/src/Faction/Factions.ts b/src/Faction/Factions.ts index 7469dee72..f0dd88620 100644 --- a/src/Faction/Factions.ts +++ b/src/Faction/Factions.ts @@ -5,11 +5,9 @@ import { Faction } from "./Faction"; import { FactionInfos } from "./FactionInfo"; -import { IMap } from "../types"; - import { Reviver } from "../utils/JSONReviver"; -export let Factions: IMap = {}; +export let Factions: Record = {}; export function loadFactions(saveString: string): void { Factions = JSON.parse(saveString, Reviver); diff --git a/src/GameOptions/ui/GameOptionsSidebar.tsx b/src/GameOptions/ui/GameOptionsSidebar.tsx index 5c8d707ff..2cfc90f77 100644 --- a/src/GameOptions/ui/GameOptionsSidebar.tsx +++ b/src/GameOptions/ui/GameOptionsSidebar.tsx @@ -19,7 +19,7 @@ import { StyleEditorButton } from "../../Themes/ui/StyleEditorButton"; import { ThemeEditorButton } from "../../Themes/ui/ThemeEditorButton"; import { ConfirmationModal } from "../../ui/React/ConfirmationModal"; import { DeleteGameButton } from "../../ui/React/DeleteGameButton"; -import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; +import { SnackbarEvents } from "../../ui/React/Snackbar"; import { SoftResetButton } from "../../ui/React/SoftResetButton"; import { Router } from "../../ui/GameRoot"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; @@ -72,7 +72,7 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => { setImportData(data); setImportSaveOpen(true); } catch (e: unknown) { - SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000); + SnackbarEvents.emit(String(e), "error", 5000); } } @@ -82,7 +82,7 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => { try { await saveObject.importGame(importData.base64); } catch (e: unknown) { - SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000); + SnackbarEvents.emit(String(e), "error", 5000); } setImportSaveOpen(false); diff --git a/src/Hacknet/HashManager.ts b/src/Hacknet/HashManager.ts index 8d12051d4..85d3ecd0a 100644 --- a/src/Hacknet/HashManager.ts +++ b/src/Hacknet/HashManager.ts @@ -9,7 +9,6 @@ import { HashUpgrades } from "./HashUpgrades"; import { HashUpgrade } from "./HashUpgrade"; -import { IMap } from "../types"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; export class HashManager { @@ -21,7 +20,7 @@ export class HashManager { hashes = 0; // Map of Hash Upgrade Name -> levels in that upgrade - upgrades: IMap = {}; + upgrades: Record = {}; constructor() { for (const name of Object.keys(HashUpgrades)) { diff --git a/src/Hacknet/HashUpgrades.ts b/src/Hacknet/HashUpgrades.ts index 59b8644dd..6b817824b 100644 --- a/src/Hacknet/HashUpgrades.ts +++ b/src/Hacknet/HashUpgrades.ts @@ -4,9 +4,8 @@ */ import { HashUpgrade, IConstructorParams } from "./HashUpgrade"; import { HashUpgradesMetadata } from "./data/HashUpgradesMetadata"; -import { IMap } from "../types"; -export const HashUpgrades: IMap = {}; +export const HashUpgrades: Record = {}; function createHashUpgrade(p: IConstructorParams): void { HashUpgrades[p.name] = new HashUpgrade(p); diff --git a/src/Literature/Literatures.ts b/src/Literature/Literatures.ts index 8f923edf7..3df893a24 100644 --- a/src/Literature/Literatures.ts +++ b/src/Literature/Literatures.ts @@ -1,10 +1,9 @@ import { CityName } from "./../Locations/data/CityNames"; import { Literature } from "./Literature"; import { LiteratureNames } from "./data/LiteratureNames"; -import { IMap } from "../types"; import { FactionNames } from "../Faction/data/FactionNames"; -export const Literatures: IMap = {}; +export const Literatures: Record = {}; (function () { let title, fn, txt; diff --git a/src/Literature/data/LiteratureNames.ts b/src/Literature/data/LiteratureNames.ts index 4d1a2c49e..712134bd5 100644 --- a/src/Literature/data/LiteratureNames.ts +++ b/src/Literature/data/LiteratureNames.ts @@ -1,6 +1,4 @@ -import { IMap } from "../../types"; - -export const LiteratureNames: IMap = { +export const LiteratureNames = { HackersStartingHandbook: "hackers-starting-handbook.lit", CorporationManagementHandbook: "corporation-management-handbook.lit", HistoryOfSynthoids: "history-of-synthoids.lit", @@ -22,4 +20,4 @@ export const LiteratureNames: IMap = { TheNewGod: "the-new-god.lit", NewTriads: "new-triads.lit", TheSecretWar: "the-secret-war.lit", -}; +} as const; diff --git a/src/Locations/Cities.ts b/src/Locations/Cities.ts index 1ec9d970a..058108950 100644 --- a/src/Locations/Cities.ts +++ b/src/Locations/Cities.ts @@ -3,6 +3,5 @@ * Key = City Name, Value = City object */ import { City } from "./City"; -import { IMap } from "../types"; -export const Cities: IMap = {}; +export const Cities: Record = {}; diff --git a/src/Locations/Locations.ts b/src/Locations/Locations.ts index 33da0eade..9171f893f 100644 --- a/src/Locations/Locations.ts +++ b/src/Locations/Locations.ts @@ -8,9 +8,7 @@ import { Location, IConstructorParams } from "./Location"; import { CityName } from "./data/CityNames"; import { LocationsMetadata } from "./data/LocationsMetadata"; -import { IMap } from "../types"; - -export const Locations: IMap = {}; +export const Locations: Record = {}; /** * Here, we'll initialize both Locations and Cities data. These can both diff --git a/src/Locations/createCityMap.ts b/src/Locations/createCityMap.ts index 590da9305..91b4cbf5b 100644 --- a/src/Locations/createCityMap.ts +++ b/src/Locations/createCityMap.ts @@ -5,10 +5,9 @@ * This map uses the official name of the city, NOT its key in the 'Cities' object */ import { Cities } from "./Cities"; -import { IMap } from "../types"; -export function createCityMap(initValue: T): IMap { - const map: IMap = {}; +export function createCityMap(initValue: T): Record { + const map: Record = {}; const cities = Object.keys(Cities); for (let i = 0; i < cities.length; ++i) { map[cities[i]] = initValue; diff --git a/src/Locations/ui/SpecialLocation.tsx b/src/Locations/ui/SpecialLocation.tsx index 0b12edf82..e003cd1f7 100644 --- a/src/Locations/ui/SpecialLocation.tsx +++ b/src/Locations/ui/SpecialLocation.tsx @@ -25,7 +25,7 @@ import { Router } from "../../ui/GameRoot"; import { Player } from "../../Player"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; -import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; +import { SnackbarEvents } from "../../ui/React/Snackbar"; import { N00dles } from "../../utils/helpers/N00dles"; import { Exploit } from "../../Exploits/Exploit"; import { applyAugmentation } from "../../Augmentation/AugmentationHelpers"; @@ -95,7 +95,7 @@ export function SpecialLocation(props: IProps): React.ReactElement { function renderNoodleBar(): React.ReactElement { function EatNoodles(): void { - SnackbarEvents.emit("You ate some delicious noodles and feel refreshed", ToastVariant.SUCCESS, 2000); + SnackbarEvents.emit("You ate some delicious noodles and feel refreshed", "success", 2000); N00dles(); // This is the true power of the noodles. if (Player.sourceFiles.length > 0) Player.giveExploit(Exploit.N00dles); if (Player.sourceFileLvl(5) > 0 || Player.bitNodeN === 5) { diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index c6b04629f..280c3b417 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -1,5 +1,4 @@ import { Player } from "../Player"; -import { IMap } from "../types"; import { NS as INS } from "../ScriptEditor/NetscriptDefinitions"; import { INetscriptExtra } from "../NetscriptFunctions/Extra"; @@ -15,7 +14,7 @@ type RamCostTree = { // TODO remember to update RamCalculations.js and WorkerScript.js // RAM costs for Netscript functions -export const RamCostConstants: IMap = { +export const RamCostConstants: Record = { ScriptBaseRamCost: 1.6, ScriptDomRamCost: 25, ScriptCorporationRamCost: 1024 - 1.6, @@ -604,7 +603,7 @@ const SourceRamCosts = { }, }; -export const RamCosts: IMap = SourceRamCosts; +export const RamCosts: Record = SourceRamCosts; // This line in particular is there so typescript typechecks that we are not missing any static ram cost. // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/src/Netscript/WorkerScript.ts b/src/Netscript/WorkerScript.ts index 3ef23d884..238b0be43 100644 --- a/src/Netscript/WorkerScript.ts +++ b/src/Netscript/WorkerScript.ts @@ -13,7 +13,6 @@ import { RunningScript } from "../Script/RunningScript"; import { Script } from "../Script/Script"; import { GetServer } from "../Server/AllServers"; import { BaseServer } from "../Server/BaseServer"; -import { IMap } from "../types"; import { NS } from "../ScriptEditor/NetscriptDefinitions"; import { ScriptDeath } from "./ScriptDeath"; import { ScriptArg } from "./ScriptArg"; @@ -43,14 +42,14 @@ export class WorkerScript { /** * Stores names of all functions that have logging disabled */ - disableLogs: IMap = {}; + disableLogs: Record = {}; /** * Used for dynamic RAM calculation. Stores names of all functions that have * already been checked by this script. * TODO: Could probably just combine this with loadedFns? */ - dynamicLoadedFns: IMap = {}; + dynamicLoadedFns: Record = {}; /** * Tracks dynamic RAM usage @@ -71,7 +70,7 @@ export class WorkerScript { * Used for static RAM calculation. Stores names of all functions that have * already been checked by this script */ - loadedFns: IMap = {}; + loadedFns: Record = {}; /** * Filename of script diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 143515678..c15235c54 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -71,7 +71,7 @@ import { NetscriptSingularity } from "./NetscriptFunctions/Singularity"; import { dialogBoxCreate } from "./ui/React/DialogBox"; import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; -import { checkEnum } from "./utils/helpers/checkEnum"; +import { checkObjContainsValue } from "./utils/helpers/checkObjContains"; import { Flags } from "./NetscriptFunctions/Flags"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; @@ -80,7 +80,17 @@ import { recentScripts } from "./Netscript/RecentScripts"; import { InternalAPI, NetscriptContext, wrapAPI } from "./Netscript/APIWrapper"; import { INetscriptExtra } from "./NetscriptFunctions/Extra"; import { ScriptDeath } from "./Netscript/ScriptDeath"; +import { TypeEquality, ValuesFrom } from "./types"; +// "Enums" as object +export const enums = { + toast: { + SUCCESS: "success", + WARNING: "warning", + ERROR: "error", + INFO: "info", + } as const, +}; export type NSFull = NS & INetscriptExtra; export function NetscriptFunctions(workerScript: WorkerScript): NSFull { @@ -89,10 +99,8 @@ export function NetscriptFunctions(workerScript: WorkerScript): NSFull { const base: InternalAPI = { args: [], - enums: { - toast: ToastVariant, - }, - + //The next line will error if enums does not match the definition in NetscriptDefinitions.d.ts + enums, singularity: NetscriptSingularity(), gang: NetscriptGang(), bladeburner: NetscriptBladeburner(), @@ -1782,12 +1790,12 @@ const base: InternalAPI = { }, toast: (ctx: NetscriptContext) => - (_message: unknown, _variant: unknown = ToastVariant.SUCCESS, _duration: unknown = 2000): void => { + (_message: unknown, _variant: unknown = enums.toast.SUCCESS, _duration: unknown = 2000): void => { const message = helpers.string(ctx, "message", _message); const variant = helpers.string(ctx, "variant", _variant); const duration = _duration === null ? null : helpers.number(ctx, "duration", _duration); - if (!checkEnum(ToastVariant, variant)) - throw new Error(`variant must be one of ${Object.values(ToastVariant).join(", ")}`); + if (!checkObjContainsValue(enums.toast, variant)) + throw new Error(`variant must be one of ${Object.values(enums.toast).join(", ")}`); SnackbarEvents.emit(message, variant, duration); }, prompt: diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts index 8c0940245..23c82bf0e 100644 --- a/src/NetscriptFunctions/Corporation.ts +++ b/src/NetscriptFunctions/Corporation.ts @@ -66,6 +66,7 @@ import { Factions } from "../Faction/Factions"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { helpers } from "../Netscript/NetscriptHelpers"; +import { checkObjContainsValue } from "../utils/helpers/checkObjContains"; export function NetscriptCorporation(): InternalAPI { function createCorporation(corporationName: string, selfFund = true): boolean { @@ -711,7 +712,7 @@ export function NetscriptCorporation(): InternalAPI { const employeeName = helpers.string(ctx, "employeeName", _employeeName); const job = helpers.string(ctx, "job", _job); - if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); + if (!checkObjContainsValue(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); const office = getOffice(divisionName, cityName); AssignJob(office, employeeName, job); @@ -725,7 +726,7 @@ export function NetscriptCorporation(): InternalAPI { const amount = helpers.number(ctx, "amount", _amount); const job = helpers.string(ctx, "job", _job); - if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); + if (!checkObjContainsValue(EmployeePositions,job)) throw new Error(`'${job}' is not a valid job.`); const office = getOffice(divisionName, cityName); return AutoAssignJob(office, job, amount); diff --git a/src/NetscriptFunctions/Infiltration.ts b/src/NetscriptFunctions/Infiltration.ts index 620e5a4bf..dd419a11c 100644 --- a/src/NetscriptFunctions/Infiltration.ts +++ b/src/NetscriptFunctions/Infiltration.ts @@ -14,7 +14,7 @@ import { import { FactionNames } from "../Faction/data/FactionNames"; import { Factions } from "../Faction/Factions"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; -import { checkEnum } from "../utils/helpers/checkEnum"; +import { checkObjContainsValue } from "../utils/helpers/checkObjContains"; import { LocationName } from "../Locations/data/LocationNames"; import { helpers } from "../Netscript/NetscriptHelpers"; @@ -24,7 +24,7 @@ export function NetscriptInfiltration(): InternalAPI { ); const calculateInfiltrationData = (ctx: NetscriptContext, locationName: string): InfiltrationLocation => { - if (!checkEnum(LocationName, locationName)) throw new Error(`Location '${locationName}' does not exists.`); + if (!checkObjContainsValue(LocationName, locationName)) throw new Error(`Location '${locationName}' does not exists.`); const location = Locations[locationName]; if (location === undefined) throw helpers.makeRuntimeErrorMsg(ctx, `Location '${location}' does not exists.`); if (location.infiltrationData === undefined) diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts index db24151dd..1359b36d6 100644 --- a/src/NetscriptFunctions/Sleeve.ts +++ b/src/NetscriptFunctions/Sleeve.ts @@ -11,7 +11,7 @@ import { SleeveSkills, SleeveTask, } from "../ScriptEditor/NetscriptDefinitions"; -import { checkEnum } from "../utils/helpers/checkEnum"; +import { checkObjContainsValue } from "../utils/helpers/checkObjContains"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBladeburnerWork"; import { isSleeveFactionWork } from "../PersonObjects/Sleeve/Work/SleeveFactionWork"; @@ -102,7 +102,7 @@ export function NetscriptSleeve(): InternalAPI { const cityName = helpers.string(ctx, "cityName", _cityName); checkSleeveAPIAccess(ctx); checkSleeveNumber(ctx, sleeveNumber); - if (checkEnum(CityName, cityName)) { + if (checkObjContainsValue(CityName, cityName)) { return Player.sleeves[sleeveNumber].travel(cityName); } else { throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`); diff --git a/src/PersonObjects/Player/PlayerObject.ts b/src/PersonObjects/Player/PlayerObject.ts index 6d5e31182..faa16699d 100644 --- a/src/PersonObjects/Player/PlayerObject.ts +++ b/src/PersonObjects/Player/PlayerObject.ts @@ -6,7 +6,6 @@ import * as generalMethods from "./PlayerObjectGeneralMethods"; import * as serverMethods from "./PlayerObjectServerMethods"; import * as workMethods from "./PlayerObjectWorkMethods"; -import { IMap } from "../../types"; import { Sleeve } from "../Sleeve/Sleeve"; import { PlayerOwnedSourceFile } from "../../SourceFile/PlayerOwnedSourceFile"; import { Exploit } from "../../Exploits/Exploit"; @@ -43,7 +42,7 @@ export class PlayerObject extends Person { hashManager = new HashManager(); hasTixApiAccess = false; hasWseAccount = false; - jobs: IMap = {}; + jobs: Record = {}; karma = 0; numPeopleKilled = 0; location = LocationName.TravelAgency; diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts index 21dde3745..bc378cfa9 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts @@ -39,7 +39,7 @@ import { numeralWrapper } from "../../ui/numeralFormat"; import { MoneySourceTracker } from "../../utils/MoneySourceTracker"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; -import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; +import { SnackbarEvents } from "../../ui/React/Snackbar"; import { achievements } from "../../Achievements/Achievements"; import { FactionNames } from "../../Faction/data/FactionNames"; @@ -257,7 +257,7 @@ export function takeDamage(this: PlayerObject, amt: number): boolean { export function hospitalize(this: PlayerObject): number { const cost = getHospitalizationCost(); - SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.WARNING, 2000); + SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, "warning", 2000); this.loseMoney(cost, "hospitalization"); this.hp.current = this.hp.max; @@ -1193,7 +1193,7 @@ export function canAccessGrafting(this: PlayerObject): boolean { export function giveExploit(this: PlayerObject, exploit: Exploit): void { if (!this.exploits.includes(exploit)) { this.exploits.push(exploit); - SnackbarEvents.emit("SF -1 acquired!", ToastVariant.SUCCESS, 2000); + SnackbarEvents.emit("SF -1 acquired!", "success", 2000); } } @@ -1202,7 +1202,7 @@ export function giveAchievement(this: PlayerObject, achievementId: string): void if (!achievement) return; if (!this.achievements.map((a) => a.ID).includes(achievementId)) { this.achievements.push({ ID: achievementId, unlockedOn: new Date().getTime() }); - SnackbarEvents.emit(`Unlocked Achievement: "${achievement.Name}"`, ToastVariant.SUCCESS, 2000); + SnackbarEvents.emit(`Unlocked Achievement: "${achievement.Name}"`, "success", 2000); } } diff --git a/src/Programs/Programs.ts b/src/Programs/Programs.ts index c6885dbaa..5c457de21 100644 --- a/src/Programs/Programs.ts +++ b/src/Programs/Programs.ts @@ -1,8 +1,7 @@ import { Program } from "./Program"; import { programsMetadata } from "./data/ProgramsMetadata"; -import { IMap } from "../types"; -export const Programs: IMap = {}; +export const Programs: Record = {}; export function initPrograms() { for (const params of programsMetadata) { Programs[params.key] = new Program(params.name, params.create, params.run); diff --git a/src/RemoteFileAPI/Remote.ts b/src/RemoteFileAPI/Remote.ts index ed83fbc21..5a5806a65 100644 --- a/src/RemoteFileAPI/Remote.ts +++ b/src/RemoteFileAPI/Remote.ts @@ -1,6 +1,6 @@ import { RFAMessage } from "./MessageDefinitions"; import { RFARequestHandler } from "./MessageHandlers"; -import { SnackbarEvents, ToastVariant } from "../ui/React/Snackbar"; +import { SnackbarEvents } from "../ui/React/Snackbar"; export class Remote { connection?: WebSocket; @@ -22,18 +22,18 @@ export class Remote { this.connection = new WebSocket(address); this.connection.addEventListener("error", (e: Event) => - SnackbarEvents.emit(`Error with websocket ${address}, details: ${JSON.stringify(e)}`, ToastVariant.ERROR, 5000), + SnackbarEvents.emit(`Error with websocket ${address}, details: ${JSON.stringify(e)}`, "error", 5000), ); this.connection.addEventListener("message", handleMessageEvent); this.connection.addEventListener("open", () => SnackbarEvents.emit( `Remote API connection established on ${this.ipaddr}:${this.port}`, - ToastVariant.SUCCESS, + "success", 2000, ), ); this.connection.addEventListener("close", () => - SnackbarEvents.emit("Remote API connection closed", ToastVariant.WARNING, 2000), + SnackbarEvents.emit("Remote API connection closed", "warning", 2000), ); } } diff --git a/src/SaveObject.tsx b/src/SaveObject.tsx index 8262f1faf..9b1c47faf 100755 --- a/src/SaveObject.tsx +++ b/src/SaveObject.tsx @@ -16,7 +16,7 @@ import { Settings } from "./Settings/Settings"; import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket"; import { staneksGift, loadStaneksGift } from "./CotMG/Helper"; -import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; +import { SnackbarEvents } from "./ui/React/Snackbar"; import * as ExportBonus from "./ExportBonus"; @@ -120,7 +120,7 @@ class BitburnerSaveObject { pushGameSaved(saveData); if (emitToastEvent) { - SnackbarEvents.emit("Game Saved!", ToastVariant.INFO, 2000); + SnackbarEvents.emit("Game Saved!", "info", 2000); } return resolve(); }) @@ -707,13 +707,9 @@ function loadGame(saveString: string): boolean { } if (saveObj.hasOwnProperty("SettingsSave")) { try { + // Try to set saved settings. Settings.load(saveObj.SettingsSave); - } catch (e) { - console.error("ERROR: Failed to parse Settings. Re-initing default values"); - Settings.init(); - } - } else { - Settings.init(); + } catch (e) {} } if (saveObj.hasOwnProperty("LastExportBonus")) { try { diff --git a/src/Script/RunningScript.ts b/src/Script/RunningScript.ts index c51cd83c6..78af0583b 100644 --- a/src/Script/RunningScript.ts +++ b/src/Script/RunningScript.ts @@ -5,7 +5,6 @@ import { Script } from "./Script"; import { ScriptUrl } from "./ScriptUrl"; import { Settings } from "../Settings/Settings"; -import { IMap } from "../types"; import { Terminal } from "../Terminal"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver"; @@ -18,7 +17,7 @@ export class RunningScript { // Map of [key: hostname] -> Hacking data. Used for offline progress calculations. // Hacking data format: [MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken] - dataMap: IMap = {}; + dataMap: Record = {}; // Script filename filename = ""; diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 7599e4fc8..a6efb5bd4 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -6573,22 +6573,16 @@ export interface NS { enums: NSEnums; } -/** @public */ -export enum ToastVariant { - SUCCESS = "success", - WARNING = "warning", - ERROR = "error", - INFO = "info", -} - -/** @public */ -export type ToastVariantValues = `${ToastVariant}`; - -/** @public */ -export interface NSEnums { - toast: typeof ToastVariant; -} +export const enums = { + toast: { + SUCCESS: "success", + WARNING: "warning", + ERROR: "error", + INFO: "info", + }, +} as const; +export type NSEnums = typeof enums; /** * Corporation Office API * @remarks diff --git a/src/Server/AllServers.ts b/src/Server/AllServers.ts index 580213bc5..13727c4da 100644 --- a/src/Server/AllServers.ts +++ b/src/Server/AllServers.ts @@ -4,7 +4,7 @@ import { serverMetadata } from "./data/servers"; import { HacknetServer } from "../Hacknet/HacknetServer"; -import { IMap, IMinMaxRange } from "../types"; +import { IMinMaxRange } from "../types"; import { createRandomIp } from "../utils/IPAddress"; import { getRandomInt } from "../utils/helpers/getRandomInt"; import { Reviver } from "../utils/JSONReviver"; @@ -17,7 +17,7 @@ import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; * Key (string) = IP * Value = Server object */ -let AllServers: IMap = {}; +let AllServers: Record = {}; function GetServerByIP(ip: string): BaseServer | undefined { for (const key of Object.keys(AllServers)) { diff --git a/src/Settings/Settings.ts b/src/Settings/Settings.ts index d477ba6e3..7846aad23 100644 --- a/src/Settings/Settings.ts +++ b/src/Settings/Settings.ts @@ -1,303 +1,98 @@ -import { ISelfInitializer, ISelfLoading } from "../types"; import { OwnedAugmentationsOrderSetting, PurchaseAugmentationsOrderSetting } from "./SettingEnums"; -import { defaultTheme, ITheme } from "../Themes/Themes"; +import { defaultTheme } from "../Themes/Themes"; import { defaultStyles } from "../Themes/Styles"; import { WordWrapOptions } from "../ScriptEditor/ui/Options"; -import { OverviewSettings } from "../ui/React/Overview"; -import { IStyleSettings } from "../ScriptEditor/NetscriptDefinitions"; -import { defaultMonacoTheme, IScriptEditorTheme } from "../ScriptEditor/ui/themes"; +import { defaultMonacoTheme } from "../ScriptEditor/ui/themes"; -/** - * Represents the default settings the player could customize. - */ -interface IDefaultSettings { - /** - * How many servers per page - */ - ActiveScriptsServerPageSize: number; - /** - * How many scripts per page - */ - ActiveScriptsScriptPageSize: number; - /** - * How often the game should autosave the player's progress, in seconds. - */ - AutosaveInterval: number; - - /** - * How many milliseconds between execution points for Netscript 1 statements. - */ - CodeInstructionRunTime: number; - - /** - * Render city as list of buttons. - */ - DisableASCIIArt: boolean; - - /** - * Whether global keyboard shortcuts should be recognized throughout the game. - */ - DisableHotkeys: boolean; - - /** - * Whether text effects such as corruption should be visible. - */ - DisableTextEffects: boolean; - - /** - * Whether overview progress bars should be visible. - */ - DisableOverviewProgressBars: boolean; - - /** - * Enable bash hotkeys - */ - EnableBashHotkeys: boolean; - - /** - * Timestamps format - */ - TimestampsFormat: string; - - /** - * Locale used for display numbers - */ - Locale: string; - - /** - * Limit the number of recently killed script entries being tracked. - */ - MaxRecentScriptsCapacity: number; - - /** - * Limit the number of log entries for each script being executed on each server. - */ - MaxLogCapacity: number; - - /** - * Limit how many entries can be written to a Netscript Port before entries start to get pushed out. - */ - MaxPortCapacity: number; - - /** - * Limit the number of entries in the terminal. - */ - MaxTerminalCapacity: number; - - /** - * Port the Remote File API client will try to connect to. - */ - RemoteFileApiPort: number; - - /** - * Save the game when you save any file. - */ - SaveGameOnFileSave: boolean; - - /** - * Whether the player should be asked to confirm purchasing each and every augmentation. - */ - SuppressBuyAugmentationConfirmation: boolean; - - /** - * Whether the user should be prompted to join each faction via a dialog box. - */ - SuppressFactionInvites: boolean; - - /** - * Whether the user should be shown a dialog box whenever they receive a new message file. - */ - SuppressMessages: boolean; - - /** - * Whether the user should be asked to confirm travelling between cities. - */ - SuppressTravelConfirmation: boolean; - - /** - * Whether the user should be displayed a popup message when his Bladeburner actions are cancelled. - */ - SuppressBladeburnerPopup: boolean; - - /** - * Whether the user should be displayed a popup message on stock market actions. - */ - SuppressTIXPopup: boolean; - - /** - * Whether the user should be displayed a toast alert when the game is saved. - */ - SuppressSavedGameToast: boolean; - - /** - * Whether the user should be displayed a toast warning when the autosave is disabled. - */ - SuppressAutosaveDisabledWarnings: boolean; - - /* - * Whether the game should skip saving the running scripts for late game - */ - ExcludeRunningScriptsFromSave: boolean; - - /* - * Theme colors - */ - theme: ITheme; - - /* - * Interface styles - */ - styles: IStyleSettings; - - /* - * Use GiB instead of GB - */ - UseIEC60027_2: boolean; - - /* - * Display intermediary time unit when their value is null - */ - ShowMiddleNullTimeUnit: boolean; - - /* - * Character overview settings - */ - overview: OverviewSettings; - - /** - * If the game's sidebar is opened - */ - IsSidebarOpened: boolean; - - /** - * Script editor theme data - */ - EditorTheme: IScriptEditorTheme; -} - -/** - * Represents all possible settings the player wants to customize to their play style. - */ -interface ISettings extends IDefaultSettings { - /** - * What order the player's owned Augmentations/Source Files should be displayed in - */ - OwnedAugmentationsOrder: OwnedAugmentationsOrderSetting; - - /** - * What order the Augmentations should be displayed in when purchasing from a Faction - */ - PurchaseAugmentationsOrder: PurchaseAugmentationsOrderSetting; - - MonacoTheme: string; - - MonacoInsertSpaces: boolean; - - MonacoFontSize: number; - - MonacoVim: boolean; - - MonacoWordWrap: WordWrapOptions; -} - -export const defaultSettings: IDefaultSettings = { +/** The current options the player has customized to their play style. */ +export const Settings = { + /** How many servers per page */ ActiveScriptsServerPageSize: 10, + /** How many scripts per page */ ActiveScriptsScriptPageSize: 10, + /** How often the game should autosave the player's progress, in seconds. */ AutosaveInterval: 60, - CodeInstructionRunTime: 50, - DisableASCIIArt: false, - DisableHotkeys: false, - DisableTextEffects: false, - DisableOverviewProgressBars: false, - EnableBashHotkeys: false, - TimestampsFormat: "", - Locale: "en", - MaxRecentScriptsCapacity: 50, - MaxLogCapacity: 50, - MaxPortCapacity: 50, - MaxTerminalCapacity: 500, - RemoteFileApiPort: 0, - SaveGameOnFileSave: true, - SuppressBuyAugmentationConfirmation: false, - SuppressFactionInvites: false, - SuppressMessages: false, - SuppressTravelConfirmation: false, - SuppressBladeburnerPopup: false, - SuppressTIXPopup: false, - SuppressSavedGameToast: false, - SuppressAutosaveDisabledWarnings: false, - UseIEC60027_2: false, - ShowMiddleNullTimeUnit: false, - ExcludeRunningScriptsFromSave: false, - IsSidebarOpened: true, - - theme: defaultTheme, - styles: defaultStyles, - overview: { x: 0, y: 0, opened: true }, - - EditorTheme: defaultMonacoTheme, -}; - -/** - * The current options the player has customized to their play style. - */ -// tslint:disable-next-line:variable-name -export const Settings: ISettings & ISelfInitializer & ISelfLoading = { - ActiveScriptsServerPageSize: defaultSettings.ActiveScriptsServerPageSize, - ActiveScriptsScriptPageSize: defaultSettings.ActiveScriptsScriptPageSize, - AutosaveInterval: defaultSettings.AutosaveInterval, + /** How many milliseconds between execution points for Netscript 1 statements. */ CodeInstructionRunTime: 25, - DisableASCIIArt: defaultSettings.DisableASCIIArt, - DisableHotkeys: defaultSettings.DisableHotkeys, - DisableTextEffects: defaultSettings.DisableTextEffects, - DisableOverviewProgressBars: defaultSettings.DisableOverviewProgressBars, - EnableBashHotkeys: defaultSettings.EnableBashHotkeys, - TimestampsFormat: defaultSettings.TimestampsFormat, + /** Whether to render city as list of buttons. */ + DisableASCIIArt: false, + /** Whether global keyboard shortcuts should be disabled throughout the game. */ + DisableHotkeys: false, + /** Whether text effects such as corruption should be disabled. */ + DisableTextEffects: false, + /** Whether overview progress bars should be visible. */ + DisableOverviewProgressBars: false, + /** Whether to enable bash hotkeys */ + EnableBashHotkeys: false, + /** Timestamps format string */ + TimestampsFormat: "", + /** Locale used for display numbers. */ Locale: "en", - MaxRecentScriptsCapacity: defaultSettings.MaxRecentScriptsCapacity, - MaxLogCapacity: defaultSettings.MaxLogCapacity, - MaxPortCapacity: defaultSettings.MaxPortCapacity, - MaxTerminalCapacity: defaultSettings.MaxTerminalCapacity, + /** Limit the number of recently killed script entries being tracked. */ + MaxRecentScriptsCapacity: 50, + /** Limit the number of log entries for each script being executed on each server. */ + MaxLogCapacity: 50, + /** Limit how many entries can be written to a Netscript Port before entries start to get pushed out. */ + MaxPortCapacity: 50, + /** Limit the number of entries in the terminal. */ + MaxTerminalCapacity: 500, + /** Port the Remote File API client will try to connect to. 0 to disable. */ + RemoteFileApiPort: 0, + /** Whether to save the game when the player saves any file. */ + SaveGameOnFileSave: true, + /** Whether to hide the confirmation dialog for augmentation purchases. */ + SuppressBuyAugmentationConfirmation: false, + /** Whether to hide the dialog showing new faction invites. */ + SuppressFactionInvites: false, + /** Whether to hide the dialog when the player receives a new message file. */ + SuppressMessages: false, + /** Whether to hide the confirmation dialog when the player attempts to travel between cities. */ + SuppressTravelConfirmation: false, + /** Whether to hide the dialog when the player's Bladeburner actions are cancelled. */ + SuppressBladeburnerPopup: false, + /** Whether to hide dialogs for stock market actions. */ + SuppressTIXPopup: false, + /** Whether to hide the toast alert when the game is saved. */ + SuppressSavedGameToast: false, + /** Whether to hide the toast warning when the autosave is disabled. */ + SuppressAutosaveDisabledWarnings: false, + /** Whether to GiB instead of GB. */ + UseIEC60027_2: false, + /** Whether to display intermediary time unit when their value is null */ + ShowMiddleNullTimeUnit: false, + /** Whether the game should skip saving the running scripts to the save file. */ + ExcludeRunningScriptsFromSave: false, + /** Whether the game's sidebar is opened. */ + IsSidebarOpened: true, + /** Theme colors. */ + theme: {...defaultTheme}, + /** Interface styles. */ + styles: {...defaultStyles}, + /** Character overview settings. */ + overview: { x: 0, y: 0, opened: true }, + /** Script editor theme data. */ + EditorTheme: {...defaultMonacoTheme}, + /** Order to display the player's owned Augmentations/Source Files. */ OwnedAugmentationsOrder: OwnedAugmentationsOrderSetting.AcquirementTime, + /** What order the Augmentations should be displayed in when purchasing from a Faction. */ PurchaseAugmentationsOrder: PurchaseAugmentationsOrderSetting.Default, - RemoteFileApiPort: defaultSettings.RemoteFileApiPort, - SaveGameOnFileSave: defaultSettings.SaveGameOnFileSave, - SuppressBuyAugmentationConfirmation: defaultSettings.SuppressBuyAugmentationConfirmation, - SuppressFactionInvites: defaultSettings.SuppressFactionInvites, - SuppressMessages: defaultSettings.SuppressMessages, - SuppressTravelConfirmation: defaultSettings.SuppressTravelConfirmation, - SuppressBladeburnerPopup: defaultSettings.SuppressBladeburnerPopup, - SuppressTIXPopup: defaultSettings.SuppressTIXPopup, - SuppressSavedGameToast: defaultSettings.SuppressSavedGameToast, - SuppressAutosaveDisabledWarnings: defaultSettings.SuppressAutosaveDisabledWarnings, - UseIEC60027_2: defaultSettings.UseIEC60027_2, - ShowMiddleNullTimeUnit: defaultSettings.ShowMiddleNullTimeUnit, - ExcludeRunningScriptsFromSave: defaultSettings.ExcludeRunningScriptsFromSave, - IsSidebarOpened: defaultSettings.IsSidebarOpened, - + /** Script editor theme. */ MonacoTheme: "monokai", MonacoInsertSpaces: false, + /** Text size for script editor. */ MonacoFontSize: 20, + /** Whether to use Vim mod by default in the script editor */ MonacoVim: false, - MonacoWordWrap: "off", - - theme: { ...defaultTheme }, - styles: { ...defaultStyles }, - overview: defaultSettings.overview, - EditorTheme: { ...defaultMonacoTheme }, - init() { - Object.assign(Settings, defaultSettings); - }, + /** Word wrap setting for Script Editor. */ + MonacoWordWrap: "off" as WordWrapOptions, + load(saveString: string) { const save = JSON.parse(saveString); - Object.assign(Settings.theme, save.theme); - delete save.theme; - Object.assign(Settings.styles, save.styles); - delete save.styles; - Object.assign(Settings.overview, save.overview); - delete save.overview; - Object.assign(Settings.EditorTheme, save.EditorTheme); - delete save.EditorTheme; + save.theme && Object.assign(Settings.theme, save.theme); + save.styles && Object.assign(Settings.styles, save.styles); + save.overview && Object.assign(Settings.overview, save.overview); + save.EditorTheme && Object.assign(Settings.EditorTheme, save.EditorTheme); + delete save.theme, save.styles, save.overview, save.EditorTheme; Object.assign(Settings, save); }, }; diff --git a/src/SourceFile/SourceFiles.tsx b/src/SourceFile/SourceFiles.tsx index 8d8f23818..086a58abd 100644 --- a/src/SourceFile/SourceFiles.tsx +++ b/src/SourceFile/SourceFiles.tsx @@ -1,9 +1,8 @@ import React from "react"; import { SourceFile } from "./SourceFile"; -import { IMap } from "../types"; import { initBitNodes, initBitNodeMultipliers } from "../BitNode/BitNode"; -export const SourceFiles: IMap = {}; +export const SourceFiles: Record = {}; /** Engine initializer for SourceFiles, BitNodes, and BitNodeMultipliers. Run once at engine load. */ export function initSourceFiles() { initBitNodes(); diff --git a/src/StockMarket/OrderProcessing.tsx b/src/StockMarket/OrderProcessing.tsx index 7c5ba6bcb..51d14a0bd 100644 --- a/src/StockMarket/OrderProcessing.tsx +++ b/src/StockMarket/OrderProcessing.tsx @@ -11,8 +11,6 @@ import { Stock } from "./Stock"; import { OrderTypes } from "./data/OrderTypes"; import { PositionTypes } from "./data/PositionTypes"; -import { IMap } from "../types"; - import { numeralWrapper } from "../ui/numeralFormat"; import { Money } from "../ui/React/Money"; @@ -23,7 +21,7 @@ import * as React from "react"; export interface IProcessOrderRefs { stockMarket: IStockMarket; - symbolToStockMap: IMap; + symbolToStockMap: Record; } /** diff --git a/src/StockMarket/StockMarket.tsx b/src/StockMarket/StockMarket.tsx index ae80b9a0d..dabc29afd 100644 --- a/src/StockMarket/StockMarket.tsx +++ b/src/StockMarket/StockMarket.tsx @@ -10,8 +10,6 @@ import { PositionTypes } from "./data/PositionTypes"; import { StockSymbols } from "./data/StockSymbols"; import { CONSTANTS } from "../Constants"; -import { IMap } from "../types"; - import { numeralWrapper } from "../ui/numeralFormat"; import { dialogBoxCreate } from "../ui/React/DialogBox"; @@ -25,7 +23,7 @@ export let StockMarket: IStockMarket = { storedCycles: 0, ticksUntilCycle: 0, } as IStockMarket; // Maps full stock name -> Stock object -export const SymbolToStockMap: IMap = {}; // Maps symbol -> Stock object +export const SymbolToStockMap: Record = {}; // Maps symbol -> Stock object export function placeOrder( stock: Stock, @@ -172,7 +170,7 @@ export function initStockMarket(): void { } export function initSymbolToStockMap(): void { - for (const name of Object.keys(StockSymbols)) { + for (const name of Object.keys(StockSymbols) as Array) { if (StockSymbols.hasOwnProperty(name)) { const stock = StockMarket[name]; if (stock == null) { diff --git a/src/StockMarket/data/StockSymbols.ts b/src/StockMarket/data/StockSymbols.ts index 707f47ca6..d41ddcf69 100644 --- a/src/StockMarket/data/StockSymbols.ts +++ b/src/StockMarket/data/StockSymbols.ts @@ -1,41 +1,40 @@ -import { IMap } from "../../types"; import { LocationName } from "../../Locations/data/LocationNames"; -export const StockSymbols: IMap = {}; +export const StockSymbols = { + // Stocks for companies at which you can work + [LocationName.AevumECorp]: "ECP", + [LocationName.Sector12MegaCorp]: "MGCP", + [LocationName.Sector12BladeIndustries]: "BLD", + [LocationName.AevumClarkeIncorporated]: "CLRK", + [LocationName.VolhavenOmniTekIncorporated]: "OMTK", + [LocationName.Sector12FourSigma]: "FSIG", + [LocationName.ChongqingKuaiGongInternational]: "KGI", + [LocationName.AevumFulcrumTechnologies]: "FLCM", + [LocationName.IshimaStormTechnologies]: "STM", + [LocationName.NewTokyoDefComm]: "DCOMM", + [LocationName.VolhavenHeliosLabs]: "HLS", + [LocationName.NewTokyoVitaLife]: "VITA", + [LocationName.Sector12IcarusMicrosystems]: "ICRS", + [LocationName.Sector12UniversalEnergy]: "UNV", + [LocationName.AevumAeroCorp]: "AERO", + [LocationName.VolhavenOmniaCybersystems]: "OMN", + [LocationName.ChongqingSolarisSpaceSystems]: "SLRS", + [LocationName.NewTokyoGlobalPharmaceuticals]: "GPH", + [LocationName.IshimaNovaMedical]: "NVMD", + [LocationName.AevumWatchdogSecurity]: "WDS", + [LocationName.VolhavenLexoCorp]: "LXO", + [LocationName.AevumRhoConstruction]: "RHOC", + [LocationName.Sector12AlphaEnterprises]: "APHE", + [LocationName.VolhavenSysCoreSecurities]: "SYSC", + [LocationName.VolhavenCompuTek]: "CTK", + [LocationName.AevumNetLinkTechnologies]: "NTLK", + [LocationName.IshimaOmegaSoftware]: "OMGA", + [LocationName.Sector12FoodNStuff]: "FNS", + [LocationName.Sector12JoesGuns]: "JGN", -// Stocks for companies at which you can work -StockSymbols[LocationName.AevumECorp] = "ECP"; -StockSymbols[LocationName.Sector12MegaCorp] = "MGCP"; -StockSymbols[LocationName.Sector12BladeIndustries] = "BLD"; -StockSymbols[LocationName.AevumClarkeIncorporated] = "CLRK"; -StockSymbols[LocationName.VolhavenOmniTekIncorporated] = "OMTK"; -StockSymbols[LocationName.Sector12FourSigma] = "FSIG"; -StockSymbols[LocationName.ChongqingKuaiGongInternational] = "KGI"; -StockSymbols[LocationName.AevumFulcrumTechnologies] = "FLCM"; -StockSymbols[LocationName.IshimaStormTechnologies] = "STM"; -StockSymbols[LocationName.NewTokyoDefComm] = "DCOMM"; -StockSymbols[LocationName.VolhavenHeliosLabs] = "HLS"; -StockSymbols[LocationName.NewTokyoVitaLife] = "VITA"; -StockSymbols[LocationName.Sector12IcarusMicrosystems] = "ICRS"; -StockSymbols[LocationName.Sector12UniversalEnergy] = "UNV"; -StockSymbols[LocationName.AevumAeroCorp] = "AERO"; -StockSymbols[LocationName.VolhavenOmniaCybersystems] = "OMN"; -StockSymbols[LocationName.ChongqingSolarisSpaceSystems] = "SLRS"; -StockSymbols[LocationName.NewTokyoGlobalPharmaceuticals] = "GPH"; -StockSymbols[LocationName.IshimaNovaMedical] = "NVMD"; -StockSymbols[LocationName.AevumWatchdogSecurity] = "WDS"; -StockSymbols[LocationName.VolhavenLexoCorp] = "LXO"; -StockSymbols[LocationName.AevumRhoConstruction] = "RHOC"; -StockSymbols[LocationName.Sector12AlphaEnterprises] = "APHE"; -StockSymbols[LocationName.VolhavenSysCoreSecurities] = "SYSC"; -StockSymbols[LocationName.VolhavenCompuTek] = "CTK"; -StockSymbols[LocationName.AevumNetLinkTechnologies] = "NTLK"; -StockSymbols[LocationName.IshimaOmegaSoftware] = "OMGA"; -StockSymbols[LocationName.Sector12FoodNStuff] = "FNS"; -StockSymbols[LocationName.Sector12JoesGuns] = "JGN"; - -// Stocks for other companies -StockSymbols["Sigma Cosmetics"] = "SGC"; -StockSymbols["Catalyst Ventures"] = "CTYS"; -StockSymbols["Microdyne Technologies"] = "MDYN"; -StockSymbols["Titan Laboratories"] = "TITN"; + // Stocks for other companies + ["Sigma Cosmetics"]: "SGC", + ["Catalyst Ventures"]: "CTYS", + ["Microdyne Technologies"]: "MDYN", + ["Titan Laboratories"]: "TITN", +} as const; diff --git a/src/StockMarket/data/TickerHeaderFormatData.ts b/src/StockMarket/data/TickerHeaderFormatData.ts index 42664268b..1ad7e8f49 100644 --- a/src/StockMarket/data/TickerHeaderFormatData.ts +++ b/src/StockMarket/data/TickerHeaderFormatData.ts @@ -5,7 +5,7 @@ export const TickerHeaderFormatData = { longestSymbol: 0, }; -for (const key of Object.keys(StockSymbols)) { +for (const key of Object.keys(StockSymbols) as Array) { TickerHeaderFormatData.longestName = Math.max(key.length, TickerHeaderFormatData.longestName); TickerHeaderFormatData.longestSymbol = Math.max(StockSymbols[key].length, TickerHeaderFormatData.longestSymbol); } diff --git a/src/Terminal/HelpText.ts b/src/Terminal/HelpText.ts index f9c85a92b..f1fff1696 100644 --- a/src/Terminal/HelpText.ts +++ b/src/Terminal/HelpText.ts @@ -1,5 +1,4 @@ /* tslint:disable:max-line-length completed-docs variable-name*/ -import { IMap } from "../types"; export const TerminalHelpText: string[] = [ "Type 'help name' to learn more about the command ", @@ -47,7 +46,7 @@ export const TerminalHelpText: string[] = [ " ", ]; -const TemplatedHelpTexts: IMap<(command: string) => string[]> = { +const TemplatedHelpTexts: Record string[]> = { scriptEditor: (command) => { return [ `Usage: ${command} [file ...] | [glob]`, @@ -70,7 +69,7 @@ const TemplatedHelpTexts: IMap<(command: string) => string[]> = { }, }; -export const HelpTexts: IMap = { +export const HelpTexts: Record = { alias: [ 'Usage: alias [-g] [name="value"] ', " ", diff --git a/src/Terminal/commands/cat.ts b/src/Terminal/commands/cat.ts index 0807e8a84..b8fcc9dd0 100644 --- a/src/Terminal/commands/cat.ts +++ b/src/Terminal/commands/cat.ts @@ -3,7 +3,7 @@ import { BaseServer } from "../../Server/BaseServer"; import { MessageFilenames, showMessage } from "../../Message/MessageHelpers"; import { showLiterature } from "../../Literature/LiteratureHelpers"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; -import { checkEnum } from "../../utils/helpers/checkEnum"; +import { checkObjContainsValue } from "../../utils/helpers/checkObjContains"; export function cat(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 1) { @@ -35,7 +35,7 @@ export function cat(args: (string | number | boolean)[], server: BaseServer): vo } else if (filename.endsWith(".msg")) { const file = server.messages[i]; if (file !== filename) continue; - if (!checkEnum(MessageFilenames, file)) return; + if (!checkObjContainsValue(MessageFilenames, file)) return; showMessage(file); return; } diff --git a/src/Themes/Themes.ts b/src/Themes/Themes.ts index 847c6fb3e..d5ec62f41 100644 --- a/src/Themes/Themes.ts +++ b/src/Themes/Themes.ts @@ -1,4 +1,3 @@ -import { IMap } from "../types"; import * as predefined from "./data"; export interface ITheme { @@ -51,6 +50,6 @@ export const defaultTheme: ITheme = { ...predefined.Default.colors, }; -export const getPredefinedThemes = (): IMap => ({ +export const getPredefinedThemes = (): Record => ({ ...predefined, }); diff --git a/src/Themes/ui/ThemeBrowser.tsx b/src/Themes/ui/ThemeBrowser.tsx index e8cee63c7..d7d9275bb 100644 --- a/src/Themes/ui/ThemeBrowser.tsx +++ b/src/Themes/ui/ThemeBrowser.tsx @@ -10,7 +10,7 @@ import { StyleEditorButton } from "./StyleEditorButton"; import { ThemeEntry } from "./ThemeEntry"; import { ThemeCollaborate } from "./ThemeCollaborate"; import { Modal } from "../../ui/React/Modal"; -import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; +import { SnackbarEvents } from "../../ui/React/Snackbar"; // Everything dies when the theme gets reloaded, so we'll keep the current scroll to not jump around. let previousScrollY = 0; @@ -49,7 +49,7 @@ export function ThemeBrowser(): React.ReactElement { UNDO , - ToastVariant.INFO, + "info", 30000, ); } diff --git a/src/Themes/ui/ThemeEditorModal.tsx b/src/Themes/ui/ThemeEditorModal.tsx index f8fd3d823..e70db847a 100644 --- a/src/Themes/ui/ThemeEditorModal.tsx +++ b/src/Themes/ui/ThemeEditorModal.tsx @@ -12,7 +12,7 @@ import PaletteSharpIcon from "@mui/icons-material/PaletteSharp"; import HistoryIcon from "@mui/icons-material/History"; import { Color, ColorPicker } from "material-ui-color"; import { ThemeEvents } from "./Theme"; -import { Settings, defaultSettings } from "../../Settings/Settings"; +import { Settings } from "../../Settings/Settings"; import { defaultTheme } from "../Themes"; import { UserInterfaceTheme } from "../../ScriptEditor/NetscriptDefinitions"; import { Router } from "../../ui/GameRoot"; @@ -150,19 +150,19 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { name="primarylight" onColorChange={onColorChange} color={customTheme["primarylight"]} - defaultColor={defaultSettings.theme["primarylight"]} + defaultColor={defaultTheme["primarylight"]} />
@@ -170,19 +170,19 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { name="successlight" onColorChange={onColorChange} color={customTheme["successlight"]} - defaultColor={defaultSettings.theme["successlight"]} + defaultColor={defaultTheme["successlight"]} />
@@ -190,19 +190,19 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { name="errorlight" onColorChange={onColorChange} color={customTheme["errorlight"]} - defaultColor={defaultSettings.theme["errorlight"]} + defaultColor={defaultTheme["errorlight"]} />
@@ -210,19 +210,19 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { name="secondarylight" onColorChange={onColorChange} color={customTheme["secondarylight"]} - defaultColor={defaultSettings.theme["secondarylight"]} + defaultColor={defaultTheme["secondarylight"]} />
@@ -230,19 +230,19 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { name="warninglight" onColorChange={onColorChange} color={customTheme["warninglight"]} - defaultColor={defaultSettings.theme["warninglight"]} + defaultColor={defaultTheme["warninglight"]} />
@@ -250,19 +250,19 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { name="infolight" onColorChange={onColorChange} color={customTheme["infolight"]} - defaultColor={defaultSettings.theme["infolight"]} + defaultColor={defaultTheme["infolight"]} />
@@ -270,43 +270,43 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { name="welllight" onColorChange={onColorChange} color={customTheme["welllight"]} - defaultColor={defaultSettings.theme["welllight"]} + defaultColor={defaultTheme["welllight"]} />
@@ -314,49 +314,49 @@ export function ThemeEditorModal(props: IProps): React.ReactElement { name="hp" onColorChange={onColorChange} color={customTheme["hp"]} - defaultColor={defaultSettings.theme["hp"]} + defaultColor={defaultTheme["hp"]} /> diff --git a/src/engine.tsx b/src/engine.tsx index 78f3d7bb5..81380c1a6 100644 --- a/src/engine.tsx +++ b/src/engine.tsx @@ -46,7 +46,7 @@ import { calculateAchievements } from "./Achievements/Achievements"; import React from "react"; import { setupUncaughtPromiseHandler } from "./UncaughtPromiseHandler"; import { Button, Typography } from "@mui/material"; -import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; +import { SnackbarEvents } from "./ui/React/Snackbar"; const Engine: { _lastUpdate: number; @@ -431,7 +431,7 @@ function warnAutosaveDisabled(): void { ); - SnackbarEvents.emit(warningToast, ToastVariant.WARNING, 5000); + SnackbarEvents.emit(warningToast, "warning", 5000); } export { Engine }; diff --git a/src/types.ts b/src/types.ts index 86bcfdead..9a5388765 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,35 +1,8 @@ -/** - * Performs an equality check between two instances of the same type. - */ -export type EqualityFunc = (a: T, b: T) => boolean; +/** Construct a type using the values from an object. Requires object to be defined "as const" */ +export type ValuesFrom = T[keyof T]; -/** - * A map is an object that holds a mapping between string keys and some consistent type. - */ -export interface IMap { - [key: string]: T; -} - -/** - * Contains a method to initialize itself to a known state. - */ -export interface ISelfInitializer { - /** - * Initialize/reset the object to a known, default state. - */ - init(): void; -} - -/** - * Contains a method to repopulate itself based on a JSON string. - */ -export interface ISelfLoading { - /** - * Loads the save state onto the current object. - * @param saveState JSON string representing the save state. - */ - load(saveState: string): void; -} +/** Only allowed to be true if the types are equal. */ +export type TypeEquality = [T1] extends [T2] ? ([T2] extends [T1] ? true : false) : false; /** * Status object for functions that return a boolean indicating success/failure diff --git a/src/ui/React/Snackbar.tsx b/src/ui/React/Snackbar.tsx index 1f3087a5a..c851129bb 100644 --- a/src/ui/React/Snackbar.tsx +++ b/src/ui/React/Snackbar.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from "react"; import { useSnackbar, SnackbarProvider as SB } from "notistack"; import makeStyles from "@mui/styles/makeStyles"; import { EventEmitter } from "../../utils/EventEmitter"; -import Alert from "@mui/material/Alert"; +import Alert, { AlertColor } from "@mui/material/Alert"; import Paper from "@mui/material/Paper"; import { logBoxBaseZIndex } from "./LogBoxManager"; @@ -10,12 +10,7 @@ interface IProps { children: React.ReactNode | React.ReactNode[]; } -export enum ToastVariant { - SUCCESS = "success", - WARNING = "warning", - ERROR = "error", - INFO = "info", -} +export type ToastVariant = AlertColor; const useStyles = makeStyles(() => ({ snackbar: { diff --git a/src/utils/StringHelperFunctions.ts b/src/utils/StringHelperFunctions.ts index eecf5db15..94133e3aa 100644 --- a/src/utils/StringHelperFunctions.ts +++ b/src/utils/StringHelperFunctions.ts @@ -1,5 +1,4 @@ import { Settings } from "../Settings/Settings"; -import { EqualityFunc } from "../types"; import { isString } from "./helpers/isString"; /* @@ -65,7 +64,7 @@ function longestCommonStart(strings: string[]): string { const a2: string = A[A.length - 1]; const L: number = a1.length; let i = 0; - const areEqualCaseInsensitive: EqualityFunc = (a: string, b: string) => a.toUpperCase() === b.toUpperCase(); + const areEqualCaseInsensitive = (a: string, b: string) => a.toUpperCase() === b.toUpperCase(); while (i < L && areEqualCaseInsensitive(a1.charAt(i), a2.charAt(i))) { i++; } diff --git a/src/utils/helpers/checkEnum.ts b/src/utils/helpers/checkEnum.ts deleted file mode 100644 index db61323fe..000000000 --- a/src/utils/helpers/checkEnum.ts +++ /dev/null @@ -1,6 +0,0 @@ -export function checkEnum( - enumVariable: { [key in T]: TEnumValue }, - value: string, -): value is TEnumValue { - return Object.values(enumVariable).includes(value); -} diff --git a/src/utils/helpers/checkObjContains.ts b/src/utils/helpers/checkObjContains.ts new file mode 100644 index 000000000..a0df51d7a --- /dev/null +++ b/src/utils/helpers/checkObjContains.ts @@ -0,0 +1,7 @@ +// This works for both enums and regular objects. +export function checkObjContainsValue>( + obj: T, + value: string, +): value is T[keyof T] { + return Object.values(obj).includes(value); +} diff --git a/test/jest/StockMarket.test.ts b/test/jest/StockMarket.test.ts index 7b1e03df4..debd53885 100644 --- a/test/jest/StockMarket.test.ts +++ b/test/jest/StockMarket.test.ts @@ -1,6 +1,5 @@ import { CONSTANTS } from "../../src/Constants"; import { Player } from "../../src/Player"; -import { IMap } from "../../src/types"; import { Company } from "../../src/Company/Company"; import { Server } from "../../src/Server/Server"; @@ -457,7 +456,7 @@ describe("Stock Market Tests", function () { it("should trigger a price update when it has enough cycles", function () { // Get the initial prices - const initialValues: IMap = {}; + const initialValues: Record = {}; for (const stockName in StockMarket) { const stock = StockMarket[stockName]; if (!(stock instanceof Stock)) { From aa80cf6451e581fd4b36c7894d110126069849ea Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 4 Oct 2022 06:40:10 -0400 Subject: [PATCH 2/8] See description Reverted ToastVariant back to an enum internally. Still exposed to player as just possible strings. Changed all 1-line documentation comments to actually be 1-line. Moved some because they were not providing documentation for the thing they were trying to. --- src/Augmentation/ui/PlayerMultipliers.tsx | 4 +- src/BitNode/BitNodeMultipliers.ts | 197 +++++------------- src/Bladeburner/Bladeburner.tsx | 8 +- src/Bladeburner/City.ts | 43 +--- src/CodingContracts.ts | 48 ++--- src/Company/Company.ts | 28 +-- src/Company/CompanyPosition.ts | 28 +-- src/Company/GetJobRequirementText.ts | 5 +- src/Corporation/Corporation.tsx | 8 +- src/Corporation/Industry.ts | 8 +- src/CotMG/ActiveFragment.ts | 8 +- src/CotMG/StaneksGift.ts | 8 +- src/DevMenu/ui/SaveFile.tsx | 4 +- src/Electron.tsx | 8 +- src/Faction/Faction.ts | 32 +-- src/Faction/FactionInfo.tsx | 40 +--- src/Faction/ui/AugmentationsPage.tsx | 4 +- src/Faction/ui/CreateGangModal.tsx | 4 +- src/Faction/ui/DonateOption.tsx | 4 +- src/GameOptions/ui/GameOptionsSidebar.tsx | 6 +- src/Gang/Gang.ts | 10 +- src/Gang/GangMember.ts | 8 +- src/Gang/data/tasks.ts | 16 +- src/Gang/ui/BonusTime.tsx | 4 +- src/Gang/ui/EquipmentsSubpage.tsx | 4 +- src/Gang/ui/GangMemberCard.tsx | 4 +- src/Gang/ui/GangMemberList.tsx | 4 +- src/Gang/ui/GangRoot.tsx | 4 +- src/Gang/ui/ManagementSubpage.tsx | 4 +- src/Gang/ui/RecruitButton.tsx | 4 +- src/Gang/ui/RecruitModal.tsx | 4 +- src/Gang/ui/TerritorySubpage.tsx | 4 +- src/Hacking.ts | 16 +- src/Hacknet/HacknetNode.ts | 8 +- src/Hacknet/HacknetServer.ts | 4 +- src/Hacknet/HashManager.ts | 20 +- src/Hacknet/HashUpgrade.ts | 10 +- src/Hacknet/ui/HacknetRoot.tsx | 4 +- src/Hacknet/ui/HashUpgradeModal.tsx | 4 +- src/Hacknet/ui/PurchaseButton.tsx | 4 +- src/Locations/City.ts | 16 +- src/Locations/Location.ts | 16 +- src/Locations/LocationTypeEnum.ts | 4 +- src/Locations/data/LocationNames.ts | 4 +- src/Locations/ui/ApplyToJobButton.tsx | 4 +- src/Locations/ui/CompanyLocation.tsx | 8 +- src/Locations/ui/HospitalLocation.tsx | 4 +- src/Locations/ui/PurchaseServerModal.tsx | 4 +- src/Locations/ui/SpecialLocation.tsx | 12 +- src/Locations/ui/TorButton.tsx | 4 +- src/Netscript/Environment.ts | 12 +- src/Netscript/Pid.ts | 4 +- src/Netscript/WorkerScript.ts | 56 ++--- .../WorkerScriptStartStopEventEmitter.ts | 4 +- src/Netscript/WorkerScripts.ts | 4 +- src/NetscriptFunctions.ts | 12 +- src/NetscriptFunctions/StockMarket.ts | 4 +- src/NetscriptWorker.ts | 8 +- src/PersonObjects/Player/PlayerObject.ts | 8 +- .../Player/PlayerObjectAugmentationMethods.ts | 4 +- .../Player/PlayerObjectGeneralMethods.ts | 8 +- .../Player/PlayerObjectServerMethods.ts | 4 +- src/PersonObjects/Sleeve/Sleeve.ts | 44 +--- src/PersonObjects/Sleeve/SleeveMethods.ts | 4 +- .../Sleeve/SleeveTaskTypesEnum.ts | 4 +- .../Sleeve/Work/SleeveBladeburnerWork.ts | 8 +- .../Sleeve/Work/SleeveClassWork.ts | 8 +- .../Sleeve/Work/SleeveCompanyWork.ts | 8 +- .../Sleeve/Work/SleeveCrimeWork.ts | 8 +- .../Sleeve/Work/SleeveFactionWork.ts | 8 +- .../Sleeve/Work/SleeveInfiltrateWork.ts | 8 +- .../Sleeve/Work/SleeveRecoveryWork.ts | 8 +- .../Sleeve/Work/SleeveSupportWork.ts | 8 +- .../Sleeve/Work/SleeveSynchroWork.ts | 8 +- .../Sleeve/ui/CovenantPurchasesRoot.tsx | 8 +- src/RedPill.tsx | 21 +- src/RemoteFileAPI/Remote.ts | 8 +- src/SaveObject.tsx | 4 +- src/Script/Script.ts | 4 +- src/ScriptEditor/NetscriptDefinitions.d.ts | 114 +++------- src/Server/BaseServer.ts | 10 +- src/Server/Server.ts | 16 +- src/Server/data/servers.ts | 40 +--- src/Settings/SettingEnums.ts | 10 +- src/StockMarket/BuyingAndSelling.tsx | 4 +- src/StockMarket/Order.ts | 8 +- src/StockMarket/Stock.ts | 88 ++------ src/StockMarket/StockMarketHelpers.ts | 3 - src/StockMarket/ui/StockMarketRoot.tsx | 4 +- src/StockMarket/ui/StockTicker.tsx | 4 +- src/StockMarket/ui/StockTickerOrder.tsx | 4 +- src/Terminal/DirectoryHelpers.ts | 8 +- src/Terminal/DirectoryServerHelpers.ts | 4 +- src/TextFile.ts | 49 ++--- src/Themes/ui/ThemeBrowser.tsx | 4 +- src/Work/ClassWork.tsx | 8 +- src/Work/CompanyWork.tsx | 8 +- src/Work/CreateProgramWork.ts | 8 +- src/Work/CrimeWork.ts | 8 +- src/Work/FactionWork.tsx | 8 +- src/Work/GraftingWork.tsx | 8 +- src/engine.tsx | 12 +- src/types.ts | 15 +- src/ui/React/Snackbar.tsx | 7 +- src/ui/Router.ts | 4 +- src/utils/EventEmitter.ts | 4 +- src/utils/helpers/createProgressBarText.ts | 16 +- src/utils/helpers/getTimestamp.ts | 4 +- src/utils/helpers/keyCodes.ts | 8 +- 109 files changed, 400 insertions(+), 1096 deletions(-) diff --git a/src/Augmentation/ui/PlayerMultipliers.tsx b/src/Augmentation/ui/PlayerMultipliers.tsx index ca7b4c58a..b78a76881 100644 --- a/src/Augmentation/ui/PlayerMultipliers.tsx +++ b/src/Augmentation/ui/PlayerMultipliers.tsx @@ -1,6 +1,3 @@ -/** - * React component for displaying the player's multipliers on the Augmentation UI page - */ import { DoubleArrow } from "@mui/icons-material"; import { List, ListItem, ListItemText, Paper, Typography } from "@mui/material"; import * as React from "react"; @@ -85,6 +82,7 @@ function MultiplierList(props: IMultiplierListProps): React.ReactElement { return listItems.length > 0 ? {listItems} : <>; } +/** React component for displaying the player's multipliers on the Augmentation UI page */ export function PlayerMultipliers(): React.ReactElement { const mults = calculateAugmentedStats(); diff --git a/src/BitNode/BitNodeMultipliers.ts b/src/BitNode/BitNodeMultipliers.ts index 566d0f14d..a773f106e 100644 --- a/src/BitNode/BitNodeMultipliers.ts +++ b/src/BitNode/BitNodeMultipliers.ts @@ -6,129 +6,79 @@ import { defaultMultipliers } from "./BitNode"; * player toward the intended strategy. Unless they really want to play the long, slow game of waiting... */ export interface IBitNodeMultipliers { - /** - * Influences how quickly the player's agility level (not exp) scales - */ + /** Influences how quickly the player's agility level (not exp) scales */ AgilityLevelMultiplier: number; - /** - * Influences the base cost to purchase an augmentation. - */ + /** Influences the base cost to purchase an augmentation. */ AugmentationMoneyCost: number; - /** - * Influences the base rep the player must have with a faction to purchase an augmentation. - */ + /** Influences the base rep the player must have with a faction to purchase an augmentation. */ AugmentationRepCost: number; - /** - * Influences how quickly the player can gain rank within Bladeburner. - */ + /** Influences how quickly the player can gain rank within Bladeburner. */ BladeburnerRank: number; - /** - * Influences the cost of skill levels from Bladeburner. - */ + /** Influences the cost of skill levels from Bladeburner. */ BladeburnerSkillCost: number; - /** - * Influences how quickly the player's charisma level (not exp) scales - */ + /** Influences how quickly the player's charisma level (not exp) scales */ CharismaLevelMultiplier: number; - /** - * Influences the experience gained for each ability when a player completes a class. - */ + /** Influences the experience gained for each ability when a player completes a class. */ ClassGymExpGain: number; - /** - * Influences the amount of money gained from completing Coding Contracts - **/ + /**Influences the amount of money gained from completing Coding Contracts. */ CodingContractMoney: number; - /** - * Influences the experience gained for each ability when the player completes working their job. - */ + /** Influences the experience gained for each ability when the player completes working their job. */ CompanyWorkExpGain: number; - /** - * Influences how much money the player earns when completing working their job. - */ + /** Influences how much money the player earns when completing working their job. */ CompanyWorkMoney: number; - /** - * Influences the valuation of corporations created by the player. - */ + /** Influences the valuation of corporations created by the player. */ CorporationValuation: number; - /** - * Influences the base experience gained for each ability when the player commits a crime. - */ + /** Influences the base experience gained for each ability when the player commits a crime. */ CrimeExpGain: number; - /** - * Influences the base money gained when the player commits a crime. - */ + /** Influences the base money gained when the player commits a crime. */ CrimeMoney: number; - /** - * Influences how many Augmentations you need in order to get invited to the Daedalus faction - */ + /** Influences how many Augmentations you need in order to get invited to the Daedalus faction */ DaedalusAugsRequirement: number; - /** - * Influences how quickly the player's defense level (not exp) scales - */ + /** Influences how quickly the player's defense level (not exp) scales */ DefenseLevelMultiplier: number; - /** - * Influences how quickly the player's dexterity level (not exp) scales - */ + /** Influences how quickly the player's dexterity level (not exp) scales */ DexterityLevelMultiplier: number; - /** - * Influences how much rep the player gains in each faction simply by being a member. - */ + /** Influences how much rep the player gains in each faction simply by being a member. */ FactionPassiveRepGain: number; - /** - * Influences the experience gained for each ability when the player completes work for a Faction. - */ + /** Influences the experience gained for each ability when the player completes work for a Faction. */ FactionWorkExpGain: number; - /** - * Influences how much rep the player gains when performing work for a faction. - */ + /** Influences how much rep the player gains when performing work for a faction. */ FactionWorkRepGain: number; - /** - * Influences how much it costs to unlock the stock market's 4S Market Data API - */ + /** Influences how much it costs to unlock the stock market's 4S Market Data API */ FourSigmaMarketDataApiCost: number; - /** - * Influences how much it costs to unlock the stock market's 4S Market Data (NOT API) - */ + /** Influences how much it costs to unlock the stock market's 4S Market Data (NOT API) */ FourSigmaMarketDataCost: number; - /** - * Reduces gangs earning. - */ + /** Reduces gangs earning. */ GangSoftcap: number; - /** - * Percentage of unique augs that the gang has. - */ + /** Percentage of unique augs that the gang has. */ GangUniqueAugs: number; - /** - * Influences the experienced gained when hacking a server. - */ + /** Influences the experienced gained when hacking a server. */ HackExpGain: number; - /** - * Influences how quickly the player's hacking level (not experience) scales - */ + /** Influences how quickly the player's hacking level (not experience) scales */ HackingLevelMultiplier: number; /** @@ -136,55 +86,38 @@ export interface IBitNodeMultipliers { * Influeces the hash rate of Hacknet Servers (unlocked in BitNode-9) */ HacknetNodeMoney: number; - - /** - * Influences how much money it costs to upgrade your home computer's RAM - */ + + /** Influences how much money it costs to upgrade your home computer's RAM */ HomeComputerRamCost: number; - - /** - * Influences how much money is gained when the player infiltrates a company. - */ + + /** Influences how much money is gained when the player infiltrates a company. */ InfiltrationMoney: number; - - /** - * Influences how much rep the player can gain from factions when selling stolen documents and secrets - */ + + /** Influences how much rep the player can gain from factions when selling stolen documents and secrets */ InfiltrationRep: number; - + /** * Influences how much money can be stolen from a server when the player performs a hack against it through * the Terminal. */ ManualHackMoney: number; - - /** - * Influence how much it costs to purchase a server - */ + + /** Influence how much it costs to purchase a server */ PurchasedServerCost: number; - - /** - * Influence how much it costs to purchase a server - */ + + /** Influence how much it costs to purchase a server */ PurchasedServerSoftcap: number; - - /** - * Influences the maximum number of purchased servers you can have - */ + + /** Influences the maximum number of purchased servers you can have */ PurchasedServerLimit: number; - - /** - * Influences the maximum allowed RAM for a purchased server - */ + + /** Influences the maximum allowed RAM for a purchased server */ PurchasedServerMaxRam: number; - /** - * Influences the minimum favor the player must have with a faction before they can donate to gain rep. - */ + + /** Influences the minimum favor the player must have with a faction before they can donate to gain rep. */ RepToDonateToFaction: number; - /** - * Influences how much money can be stolen from a server when a script performs a hack against it. - */ + /** Influences how much money can be stolen from a server when a script performs a hack against it. */ ScriptHackMoney: number; /** @@ -194,62 +127,40 @@ export interface IBitNodeMultipliers { */ ScriptHackMoneyGain: number; - /** - * Influences the growth percentage per cycle against a server. - */ + /** Influences the growth percentage per cycle against a server. */ ServerGrowthRate: number; - /** - * Influences the maxmimum money that a server can grow to. - */ + /** Influences the maxmimum money that a server can grow to. */ ServerMaxMoney: number; - /** - * Influences the initial money that a server starts with. - */ + /** Influences the initial money that a server starts with. */ ServerStartingMoney: number; - /** - * Influences the initial security level (hackDifficulty) of a server. - */ + /** Influences the initial security level (hackDifficulty) of a server. */ ServerStartingSecurity: number; - /** - * Influences the weaken amount per invocation against a server. - */ + /** Influences the weaken amount per invocation against a server. */ ServerWeakenRate: number; - /** - * Influences how quickly the player's strength level (not exp) scales - */ + /** Influences how quickly the player's strength level (not exp) scales */ StrengthLevelMultiplier: number; - /** - * Influences the power of the gift. - */ + /** Influences the power of the gift. */ StaneksGiftPowerMultiplier: number; - /** - * Influences the size of the gift. - */ + /** Influences the size of the gift. */ StaneksGiftExtraSize: number; - /** - * Influences the hacking skill required to backdoor the world daemon. - */ + /** Influences the hacking skill required to backdoor the world daemon. */ WorldDaemonDifficulty: number; - /** - * Influences corporation dividends. - */ + /** Influences corporation dividends. */ CorporationSoftcap: number; // Index signature [key: string]: number; } -/** - * The multipliers that are influenced by current Bitnode progression. - */ +/** The multipliers that are influenced by current Bitnode progression. */ // tslint:disable-next-line:variable-name export const BitNodeMultipliers = Object.assign({}, defaultMultipliers); diff --git a/src/Bladeburner/Bladeburner.tsx b/src/Bladeburner/Bladeburner.tsx index 00cef4634..9f66b8a81 100644 --- a/src/Bladeburner/Bladeburner.tsx +++ b/src/Bladeburner/Bladeburner.tsx @@ -2377,16 +2377,12 @@ export class Bladeburner { } } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("Bladeburner", this); } - /** - * Initiatizes a Bladeburner object from a JSON save state. - */ + /** Initiatizes a Bladeburner object from a JSON save state. */ static fromJSON(value: IReviverValue): Bladeburner { return Generic_fromJSON(Bladeburner, value.data); } diff --git a/src/Bladeburner/City.ts b/src/Bladeburner/City.ts index 7ead8c7e5..21a22db8b 100644 --- a/src/Bladeburner/City.ts +++ b/src/Bladeburner/City.ts @@ -4,7 +4,9 @@ import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../uti import { addOffset } from "../utils/helpers/addOffset"; interface IChangePopulationByCountParams { + /** How much the estimate should change by. */ estChange: number; + /** Add offset to estimate (offset by percentage). */ estOffset: number; } @@ -14,29 +16,19 @@ interface IChangePopulationByPercentageParams { } export class City { - /** - * Name of the city. - */ + /** Name of the city. */ name = ""; - /** - * Population of the city. - */ + /** Population of the city. */ pop = 0; - /** - * Population estimation of the city. - */ + /** Population estimation of the city. */ popEst = 0; - /** - * Number of communities in the city. - */ + /** Number of communities in the city. */ comms = 0; - /** - * Chaos level of the city. - */ + /** Chaos level of the city. */ chaos = 0; constructor(name: string = BladeburnerConstants.CityNames[2]) { @@ -51,9 +43,7 @@ export class City { this.chaos = 0; } - /** - * p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%) - */ + /** p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%) */ changeChaosByPercentage(p: number): void { if (isNaN(p)) { throw new Error("NaN passed into City.chaosChaosByPercentage()"); @@ -84,9 +74,7 @@ export class City { } } - /** - * p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%) - */ + /** p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%) */ improvePopulationEstimateByPercentage(p: number, skillMult = 1): void { p = p * skillMult; if (isNaN(p)) { @@ -106,11 +94,6 @@ export class City { } } - /** - * @params options: - * estChange(int): How much the estimate should change by - * estOffset(int): Add offset to estimate (offset by percentage) - */ changePopulationByCount(n: number, params: IChangePopulationByCountParams = { estChange: 0, estOffset: 0 }): void { if (isNaN(n)) { throw new Error("NaN passed into City.changePopulationByCount()"); @@ -174,16 +157,12 @@ export class City { } } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("City", this); } - /** - * Initiatizes a City object from a JSON save state. - */ + /** Initiatizes a City object from a JSON save state. */ static fromJSON(value: IReviverValue): City { return Generic_fromJSON(City, value.data); } diff --git a/src/CodingContracts.ts b/src/CodingContracts.ts index caf8cba1d..fd19a546a 100644 --- a/src/CodingContracts.ts +++ b/src/CodingContracts.ts @@ -7,34 +7,22 @@ import { CodingContractEvent } from "./ui/React/CodingContractModal"; /* Represents different types of problems that a Coding Contract can have */ class CodingContractType { - /** - * Function that generates a description of the problem - */ + /** Function that generates a description of the problem */ desc: DescriptionFunc; - /** - * Number that generally represents the problem's difficulty. Bigger numbers = harder - */ + /** Number that generally represents the problem's difficulty. Bigger numbers = harder */ difficulty: number; - /** - * A function that randomly generates a valid 'data' for the problem - */ + /** A function that randomly generates a valid 'data' for the problem */ generate: GeneratorFunc; - /** - * Name of the type of problem - */ + /** Name of the type of problem */ name: string; - /** - * The maximum number of tries the player gets on this kind of problem before it self-destructs - */ + /** The maximum number of tries the player gets on this kind of problem before it self-destructs */ numTries: number; - /** - * Stores a function that checks if the provided answer is correct - */ + /** Stores a function that checks if the provided answer is correct */ solver: SolverFunc; constructor( @@ -70,9 +58,7 @@ for (const md of codingContractTypesMetadata) { ); } -/** - * Enum representing the different types of rewards a Coding Contract can give - */ +/** Enum representing the different types of rewards a Coding Contract can give */ export enum CodingContractRewardType { FactionReputation, FactionReputationAll, @@ -80,18 +66,14 @@ export enum CodingContractRewardType { Money, // This must always be the last reward type } -/** - * Enum representing the result when trying to solve the Contract - */ +/** Enum representing the result when trying to solve the Contract */ export enum CodingContractResult { Success, Failure, Cancelled, } -/** - * A class that represents the type of reward a contract gives - */ +/** A class that represents the type of reward a contract gives */ export interface ICodingContractReward { /* Name of Company/Faction name for reward, if applicable */ name?: string; @@ -159,9 +141,7 @@ export class CodingContract { return CodingContractTypes[this.type].solver(this.data, solution); } - /** - * Creates a popup to prompt the player to solve the problem - */ + /** Creates a popup to prompt the player to solve the problem */ async prompt(): Promise { return new Promise((resolve) => { const props = { @@ -181,16 +161,12 @@ export class CodingContract { }); } - /** - * Serialize the current file to a JSON save state. - */ + /** Serialize the current file to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("CodingContract", this); } - /** - * Initiatizes a CodingContract from a JSON save state. - */ + /** Initiatizes a CodingContract from a JSON save state. */ static fromJSON(value: IReviverValue): CodingContract { return Generic_fromJSON(CodingContract, value.data); } diff --git a/src/Company/Company.ts b/src/Company/Company.ts index 70081eaf3..5c0afe0ee 100644 --- a/src/Company/Company.ts +++ b/src/Company/Company.ts @@ -24,19 +24,13 @@ const DefaultConstructorParams: IConstructorParams = { }; export class Company { - /** - * Company name - */ + /** Company name */ name: string; - /** - * Description and general information about company - */ + /** Description and general information about company */ info: string; - /** - * Has faction associated. - */ + /** Has faction associated. */ isMegacorp: boolean; /** @@ -48,9 +42,7 @@ export class Company { */ companyPositions: Record; - /** - * Company-specific multiplier for earnings - */ + /** Company-specific multiplier for earnings */ expMultiplier: number; salaryMultiplier: number; @@ -63,9 +55,7 @@ export class Company { */ jobStatReqOffset: number; - /** - * Properties to track the player's progress in this company - */ + /** Properties to track the player's progress in this company */ isPlayerEmployed: boolean; playerReputation: number; favor: number; @@ -142,16 +132,12 @@ export class Company { return newFavor - this.favor; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("Company", this); } - /** - * Initiatizes a Company from a JSON save state. - */ + /** Initiatizes a Company from a JSON save state. */ static fromJSON(value: IReviverValue): Company { return Generic_fromJSON(Company, value.data); } diff --git a/src/Company/CompanyPosition.ts b/src/Company/CompanyPosition.ts index afa8a0452..0206e9639 100644 --- a/src/Company/CompanyPosition.ts +++ b/src/Company/CompanyPosition.ts @@ -33,14 +33,10 @@ export interface IConstructorParams { } export class CompanyPosition { - /** - * Position title - */ + /** Position title */ name: string; - /** - * Title of next position to be promoted to - */ + /** Title of next position to be promoted to */ nextPosition: string | null; /** @@ -49,14 +45,10 @@ export class CompanyPosition { */ baseSalary: number; - /** - * Reputation multiplier - */ + /** Reputation multiplier */ repMultiplier: number; - /** - * Required stats to earn this position - */ + /** Required stats to earn this position */ requiredAgility: number; requiredCharisma: number; requiredDefense: number; @@ -64,14 +56,10 @@ export class CompanyPosition { requiredHacking: number; requiredStrength: number; - /** - * Required company reputation to earn this position - */ + /** Required company reputation to earn this position */ requiredReputation: number; - /** - * Effectiveness of each stat time for job performance - */ + /** Effectiveness of each stat time for job performance */ hackingEffectiveness: number; strengthEffectiveness: number; defenseEffectiveness: number; @@ -79,9 +67,7 @@ export class CompanyPosition { agilityEffectiveness: number; charismaEffectiveness: number; - /** - * Experience gain for performing job (per 200ms game cycle) - */ + /** Experience gain for performing job (per 200ms game cycle) */ hackingExpGain: number; strengthExpGain: number; defenseExpGain: number; diff --git a/src/Company/GetJobRequirementText.ts b/src/Company/GetJobRequirementText.ts index 45bbb51cd..9fba7b87b 100644 --- a/src/Company/GetJobRequirementText.ts +++ b/src/Company/GetJobRequirementText.ts @@ -1,10 +1,7 @@ import { Company } from "./Company"; import { CompanyPosition } from "./CompanyPosition"; -/** - * Returns a string with the given CompanyPosition's stat requirements - */ - +/** Returns a string with the given CompanyPosition's stat requirements */ export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext = false): string { let reqText = ""; const offset: number = company.jobStatReqOffset; diff --git a/src/Corporation/Corporation.tsx b/src/Corporation/Corporation.tsx index dacb5ea24..b69a216f0 100644 --- a/src/Corporation/Corporation.tsx +++ b/src/Corporation/Corporation.tsx @@ -446,16 +446,12 @@ export class Corporation { return; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("Corporation", this); } - /** - * Initiatizes a Corporation object from a JSON save state. - */ + /** Initiatizes a Corporation object from a JSON save state. */ static fromJSON(value: IReviverValue): Corporation { return Generic_fromJSON(Corporation, value.data); } diff --git a/src/Corporation/Industry.ts b/src/Corporation/Industry.ts index fe1a6d8a8..dd2c75a0f 100644 --- a/src/Corporation/Industry.ts +++ b/src/Corporation/Industry.ts @@ -1369,16 +1369,12 @@ export class Industry { return researchTree.getStorageMultiplier(); } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("Industry", this); } - /** - * Initiatizes a Industry object from a JSON save state. - */ + /** Initiatizes a Industry object from a JSON save state. */ static fromJSON(value: IReviverValue): Industry { return Generic_fromJSON(Industry, value.data); } diff --git a/src/CotMG/ActiveFragment.ts b/src/CotMG/ActiveFragment.ts index 10bee93b4..aaea55780 100644 --- a/src/CotMG/ActiveFragment.ts +++ b/src/CotMG/ActiveFragment.ts @@ -71,16 +71,12 @@ export class ActiveFragment { return Object.assign({}, this); } - /** - * Serialize an active fragment to a JSON save state. - */ + /** Serialize an active fragment to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("ActiveFragment", this); } - /** - * Initializes an acive fragment from a JSON save state - */ + /** Initializes an acive fragment from a JSON save state */ static fromJSON(value: IReviverValue): ActiveFragment { return Generic_fromJSON(ActiveFragment, value.data); } diff --git a/src/CotMG/StaneksGift.ts b/src/CotMG/StaneksGift.ts index a914c4b6e..9bb235c1f 100644 --- a/src/CotMG/StaneksGift.ts +++ b/src/CotMG/StaneksGift.ts @@ -230,16 +230,12 @@ export class StaneksGift extends BaseGift { this.storedCycles = 0; } - /** - * Serialize Staneks Gift to a JSON save state. - */ + /** Serialize Staneks Gift to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("StaneksGift", this); } - /** - * Initializes Staneks Gift from a JSON save state - */ + /** Initializes Staneks Gift from a JSON save state */ static fromJSON(value: IReviverValue): StaneksGift { return Generic_fromJSON(StaneksGift, value.data); } diff --git a/src/DevMenu/ui/SaveFile.tsx b/src/DevMenu/ui/SaveFile.tsx index 0d2ff3391..8f7d9003b 100644 --- a/src/DevMenu/ui/SaveFile.tsx +++ b/src/DevMenu/ui/SaveFile.tsx @@ -7,7 +7,7 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import Typography from "@mui/material/Typography"; import { saveObject } from "../../SaveObject"; -import { SnackbarEvents } from "../../ui/React/Snackbar"; +import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; import { Upload } from "@mui/icons-material"; import { Button } from "@mui/material"; import { OptionSwitch } from "../../ui/React/OptionSwitch"; @@ -25,7 +25,7 @@ export function SaveFile(): React.ReactElement { const save = atob(base64Save); setSaveFile(save); } catch (e: unknown) { - SnackbarEvents.emit(String(e), "error", 5000); + SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000); } } diff --git a/src/Electron.tsx b/src/Electron.tsx index 89d61112c..6d28de1c2 100644 --- a/src/Electron.tsx +++ b/src/Electron.tsx @@ -151,7 +151,7 @@ function initSaveFunctions(): void { saveObject.exportGame(); } catch (error) { console.error(error); - SnackbarEvents.emit("Could not export game.", "error", 2000); + SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000); } }, triggerScriptsExport: (): void => exportScripts("*", Player.getHomeComputer()), @@ -203,7 +203,7 @@ function initElectronBridge(): void { }) .catch((error: unknown) => { console.error(error); - SnackbarEvents.emit("Could not save game.", "error", 2000); + SnackbarEvents.emit("Could not save game.", ToastVariant.ERROR, 2000); }); }); bridge.receive("trigger-game-export", () => { @@ -211,7 +211,7 @@ function initElectronBridge(): void { window.appSaveFns.triggerGameExport(); } catch (error) { console.error(error); - SnackbarEvents.emit("Could not export game.", "error", 2000); + SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000); } }); bridge.receive("trigger-scripts-export", () => { @@ -219,7 +219,7 @@ function initElectronBridge(): void { window.appSaveFns.triggerScriptsExport(); } catch (error) { console.error(error); - SnackbarEvents.emit("Could not export scripts.", "error", 2000); + SnackbarEvents.emit("Could not export scripts.", ToastVariant.ERROR, 2000); } }); } diff --git a/src/Faction/Faction.ts b/src/Faction/Faction.ts index 95258cba6..ee50360b6 100644 --- a/src/Faction/Faction.ts +++ b/src/Faction/Faction.ts @@ -9,34 +9,22 @@ export class Faction { */ alreadyInvited = false; - /** - * Holds names of all augmentations that this Faction offers - */ + /** Holds names of all augmentations that this Faction offers */ augmentations: string[] = []; - /** - * Amount of favor the player has with this faction. - */ + /** Amount of favor the player has with this faction. */ favor = 0; - /** - * Flag signalling whether player has been banned from this faction - */ + /** Flag signalling whether player has been banned from this faction */ isBanned = false; - /** - * Flag signalling whether player is a member of this faction - */ + /** Flag signalling whether player is a member of this faction */ isMember = false; - /** - * Name of faction - */ + /** Name of faction */ name = ""; - /** - * Amount of reputation player has with this faction - */ + /** Amount of reputation player has with this faction */ playerReputation = 0; constructor(name = "") { @@ -72,16 +60,12 @@ export class Faction { return newFavor - this.favor; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("Faction", this); } - /** - * Initiatizes a Faction object from a JSON save state. - */ + /** Initiatizes a Faction object from a JSON save state. */ static fromJSON(value: IReviverValue): Faction { return Generic_fromJSON(Faction, value.data); } diff --git a/src/Faction/FactionInfo.tsx b/src/Faction/FactionInfo.tsx index 1dfd62b5a..3270e2a3b 100644 --- a/src/Faction/FactionInfo.tsx +++ b/src/Faction/FactionInfo.tsx @@ -15,48 +15,30 @@ interface FactionInfoParams { assignment?: () => React.ReactElement; } -/** - * Contains the "information" property for all the Factions, which is just a description of each faction - */ +/** Contains the "information" property for all the Factions, which is just a description of each faction */ export class FactionInfo { - /** - * The names of all other factions considered to be enemies to this faction. - */ + /** The names of all other factions considered to be enemies to this faction. */ enemies: string[]; - /** - * The descriptive text to show on the faction's page. - */ + /** The descriptive text to show on the faction's page. */ infoText: JSX.Element; - /** - * A flag indicating if the faction supports field work to earn reputation. - */ + /** A flag indicating if the faction supports field work to earn reputation. */ offerFieldWork: boolean; - /** - * A flag indicating if the faction supports hacking work to earn reputation. - */ + /** A flag indicating if the faction supports hacking work to earn reputation. */ offerHackingWork: boolean; - /** - * A flag indicating if the faction supports security work to earn reputation. - */ + /** A flag indicating if the faction supports security work to earn reputation. */ offerSecurityWork: boolean; - /** - * Keep faction on install. - */ + /** Keep faction on install. */ keep: boolean; - /** - * Special faction - */ + /** Special faction */ special: boolean; - /** - * The data to display on the faction screen. - */ + /** The data to display on the faction screen. */ assignment?: () => React.ReactElement; constructor(params: FactionInfoParams) { @@ -76,9 +58,7 @@ export class FactionInfo { } } -/** - * A map of all factions and associated info to them. - */ +/** A map of all factions and associated info to them. */ // tslint:disable-next-line:variable-name export const FactionInfos: Record = { // Endgame diff --git a/src/Faction/ui/AugmentationsPage.tsx b/src/Faction/ui/AugmentationsPage.tsx index 939ad8e0e..dfdeac079 100644 --- a/src/Faction/ui/AugmentationsPage.tsx +++ b/src/Faction/ui/AugmentationsPage.tsx @@ -1,6 +1,3 @@ -/** - * Root React Component for displaying a faction's "Purchase Augmentations" page - */ import { Box, Button, Tooltip, Typography, Paper, Container } from "@mui/material"; import React, { useState } from "react"; @@ -23,6 +20,7 @@ type IProps = { routeToMainPage: () => void; }; +/** Root React Component for displaying a faction's "Purchase Augmentations" page */ export function AugmentationsPage(props: IProps): React.ReactElement { const setRerender = useState(false)[1]; diff --git a/src/Faction/ui/CreateGangModal.tsx b/src/Faction/ui/CreateGangModal.tsx index 83064b385..2b50d08bf 100644 --- a/src/Faction/ui/CreateGangModal.tsx +++ b/src/Faction/ui/CreateGangModal.tsx @@ -1,6 +1,3 @@ -/** - * React Component for the popup used to create a new gang. - */ import React from "react"; import { Modal } from "../../ui/React/Modal"; import { Router } from "../../ui/GameRoot"; @@ -16,6 +13,7 @@ interface IProps { facName: string; } +/** React Component for the popup used to create a new gang. */ export function CreateGangModal(props: IProps): React.ReactElement { const combatGangText = "This is a COMBAT gang. Members in this gang will have different tasks than HACKING gangs. " + diff --git a/src/Faction/ui/DonateOption.tsx b/src/Faction/ui/DonateOption.tsx index 052b7d397..fcfb872c6 100644 --- a/src/Faction/ui/DonateOption.tsx +++ b/src/Faction/ui/DonateOption.tsx @@ -1,6 +1,3 @@ -/** - * React component for a donate option on the Faction UI - */ import React, { useState } from "react"; import { CONSTANTS } from "../../Constants"; @@ -27,6 +24,7 @@ type IProps = { rerender: () => void; }; +/** React component for a donate option on the Faction UI */ export function DonateOption(props: IProps): React.ReactElement { const [donateAmt, setDonateAmt] = useState(NaN); const digits = (CONSTANTS.DonateMoneyToRepDivisor + "").length - 1; diff --git a/src/GameOptions/ui/GameOptionsSidebar.tsx b/src/GameOptions/ui/GameOptionsSidebar.tsx index 2cfc90f77..5c8d707ff 100644 --- a/src/GameOptions/ui/GameOptionsSidebar.tsx +++ b/src/GameOptions/ui/GameOptionsSidebar.tsx @@ -19,7 +19,7 @@ import { StyleEditorButton } from "../../Themes/ui/StyleEditorButton"; import { ThemeEditorButton } from "../../Themes/ui/ThemeEditorButton"; import { ConfirmationModal } from "../../ui/React/ConfirmationModal"; import { DeleteGameButton } from "../../ui/React/DeleteGameButton"; -import { SnackbarEvents } from "../../ui/React/Snackbar"; +import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; import { SoftResetButton } from "../../ui/React/SoftResetButton"; import { Router } from "../../ui/GameRoot"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; @@ -72,7 +72,7 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => { setImportData(data); setImportSaveOpen(true); } catch (e: unknown) { - SnackbarEvents.emit(String(e), "error", 5000); + SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000); } } @@ -82,7 +82,7 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => { try { await saveObject.importGame(importData.base64); } catch (e: unknown) { - SnackbarEvents.emit(String(e), "error", 5000); + SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000); } setImportSaveOpen(false); diff --git a/src/Gang/Gang.ts b/src/Gang/Gang.ts index 32fe4f60c..7745fcd54 100644 --- a/src/Gang/Gang.ts +++ b/src/Gang/Gang.ts @@ -376,7 +376,7 @@ export class Gang { return Math.max(1, discount); } - // Returns only valid tasks for this gang. Excludes 'Unassigned' + /** Returns only valid tasks for this gang. Excludes 'Unassigned' */ getAllTaskNames(): string[] { return Object.keys(GangMemberTasks).filter((taskName: string) => { const task = GangMemberTasks[taskName]; @@ -394,16 +394,12 @@ export class Gang { return upg.cost / this.getDiscount(); } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("Gang", this); } - /** - * Initiatizes a Gang object from a JSON save state. - */ + /** Initiatizes a Gang object from a JSON save state. */ static fromJSON(value: IReviverValue): Gang { return Generic_fromJSON(Gang, value.data); } diff --git a/src/Gang/GangMember.ts b/src/Gang/GangMember.ts index 177b10f8d..65f42576b 100644 --- a/src/Gang/GangMember.ts +++ b/src/Gang/GangMember.ts @@ -319,16 +319,12 @@ export class GangMember { return true; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("GangMember", this); } - /** - * Initiatizes a GangMember object from a JSON save state. - */ + /** Initiatizes a GangMember object from a JSON save state. */ static fromJSON(value: IReviverValue): GangMember { return Generic_fromJSON(GangMember, value.data); } diff --git a/src/Gang/data/tasks.ts b/src/Gang/data/tasks.ts index 58322e913..c563302bf 100644 --- a/src/Gang/data/tasks.ts +++ b/src/Gang/data/tasks.ts @@ -6,24 +6,16 @@ import { ITaskParams } from "../ITaskParams"; * (defined in Gang.js) */ interface IGangMemberTaskMetadata { - /** - * Description of the task - */ + /** Description of the task */ desc: string; - /** - * Whether or not this task is meant for Combat-type gangs - */ + /** Whether or not this task is meant for Combat-type gangs */ isCombat: boolean; - /** - * Whether or not this task is for Hacking-type gangs - */ + /** Whether or not this task is for Hacking-type gangs */ isHacking: boolean; - /** - * Name of the task - */ + /** Name of the task */ name: string; /** diff --git a/src/Gang/ui/BonusTime.tsx b/src/Gang/ui/BonusTime.tsx index 69364ed1e..a7e0af2b9 100644 --- a/src/Gang/ui/BonusTime.tsx +++ b/src/Gang/ui/BonusTime.tsx @@ -1,6 +1,3 @@ -/** - * React Component for displaying the bonus time remaining. - */ import * as React from "react"; import { Gang } from "../Gang"; import { CONSTANTS } from "../../Constants"; @@ -13,6 +10,7 @@ interface IProps { gang: Gang; } +/** React Component for displaying the bonus time remaining. */ export function BonusTime(props: IProps): React.ReactElement { const CyclerPerSecond = 1000 / CONSTANTS._idleSpeed; if ((props.gang.storedCycles / CyclerPerSecond) * 1000 <= 5000) return <>; diff --git a/src/Gang/ui/EquipmentsSubpage.tsx b/src/Gang/ui/EquipmentsSubpage.tsx index 3ab0a0850..76efd5bea 100644 --- a/src/Gang/ui/EquipmentsSubpage.tsx +++ b/src/Gang/ui/EquipmentsSubpage.tsx @@ -1,6 +1,3 @@ -/** - * React Component for the popup that manages gang members upgrades - */ import React, { useState } from "react"; import { useGang } from "./Context"; @@ -244,6 +241,7 @@ function GangMemberUpgradePanel(props: IPanelProps): React.ReactElement { ); } +/** React Component for the popup that manages gang members upgrades */ export function EquipmentsSubpage(): React.ReactElement { const gang = useGang(); const [filter, setFilter] = useState(""); diff --git a/src/Gang/ui/GangMemberCard.tsx b/src/Gang/ui/GangMemberCard.tsx index c50fb9bb6..f4ab25127 100644 --- a/src/Gang/ui/GangMemberCard.tsx +++ b/src/Gang/ui/GangMemberCard.tsx @@ -1,6 +1,3 @@ -/** - * React Component for a gang member on the management subpage. - */ import React from "react"; import { GangMember } from "../GangMember"; import { GangMemberCardContent } from "./GangMemberCardContent"; @@ -14,6 +11,7 @@ interface IProps { member: GangMember; } +/** React Component for a gang member on the management subpage. */ export function GangMemberCard(props: IProps): React.ReactElement { return ( diff --git a/src/Gang/ui/GangMemberList.tsx b/src/Gang/ui/GangMemberList.tsx index 3effe6508..411543b73 100644 --- a/src/Gang/ui/GangMemberList.tsx +++ b/src/Gang/ui/GangMemberList.tsx @@ -1,6 +1,3 @@ -/** - * React Component for the list of gang members on the management subpage. - */ import React, { useState } from "react"; import { GangMemberCard } from "./GangMemberCard"; import { RecruitButton } from "./RecruitButton"; @@ -12,6 +9,7 @@ import SearchIcon from "@mui/icons-material/Search"; import { GangMember } from "../GangMember"; import { OptionSwitch } from "../../ui/React/OptionSwitch"; +/** React Component for the list of gang members on the management subpage. */ export function GangMemberList(): React.ReactElement { const gang = useGang(); const setRerender = useState(false)[1]; diff --git a/src/Gang/ui/GangRoot.tsx b/src/Gang/ui/GangRoot.tsx index a64164b1c..743e58d54 100644 --- a/src/Gang/ui/GangRoot.tsx +++ b/src/Gang/ui/GangRoot.tsx @@ -1,6 +1,3 @@ -/** - * React Component for all the gang stuff. - */ import React, { useState, useEffect } from "react"; import { ManagementSubpage } from "./ManagementSubpage"; import { TerritorySubpage } from "./TerritorySubpage"; @@ -11,6 +8,7 @@ import { Context } from "./Context"; import Tabs from "@mui/material/Tabs"; import Tab from "@mui/material/Tab"; +/** React Component for all the gang stuff. */ export function GangRoot(): React.ReactElement { const gang = (function () { if (Player.gang === null) throw new Error("Gang should not be null"); diff --git a/src/Gang/ui/ManagementSubpage.tsx b/src/Gang/ui/ManagementSubpage.tsx index 6f42a1aa8..9dc2f5175 100644 --- a/src/Gang/ui/ManagementSubpage.tsx +++ b/src/Gang/ui/ManagementSubpage.tsx @@ -1,12 +1,10 @@ -/** - * React Component for the subpage that manages gang members, the main page. - */ import React from "react"; import { GangStats } from "./GangStats"; import { GangMemberList } from "./GangMemberList"; import { useGang } from "./Context"; import Typography from "@mui/material/Typography"; +/** React Component for the subpage that manages gang members, the main page. */ export function ManagementSubpage(): React.ReactElement { const gang = useGang(); return ( diff --git a/src/Gang/ui/RecruitButton.tsx b/src/Gang/ui/RecruitButton.tsx index 039c9de46..8fe5d9094 100644 --- a/src/Gang/ui/RecruitButton.tsx +++ b/src/Gang/ui/RecruitButton.tsx @@ -1,6 +1,3 @@ -/** - * React Component for the recruitment button and text on the gang main page. - */ import React, { useState } from "react"; import { RecruitModal } from "./RecruitModal"; import { GangConstants } from "../data/Constants"; @@ -14,6 +11,7 @@ interface IProps { onRecruit: () => void; } +/** React Component for the recruitment button and text on the gang main page. */ export function RecruitButton(props: IProps): React.ReactElement { const gang = useGang(); const [open, setOpen] = useState(false); diff --git a/src/Gang/ui/RecruitModal.tsx b/src/Gang/ui/RecruitModal.tsx index 4c81c36fc..c1150320f 100644 --- a/src/Gang/ui/RecruitModal.tsx +++ b/src/Gang/ui/RecruitModal.tsx @@ -1,6 +1,3 @@ -/** - * React Component for the popup used to recruit new gang members. - */ import React, { useState } from "react"; import { Modal } from "../../ui/React/Modal"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; @@ -16,6 +13,7 @@ interface IRecruitPopupProps { onRecruit: () => void; } +/** React Component for the popup used to recruit new gang members. */ export function RecruitModal(props: IRecruitPopupProps): React.ReactElement { const gang = useGang(); const [name, setName] = useState(""); diff --git a/src/Gang/ui/TerritorySubpage.tsx b/src/Gang/ui/TerritorySubpage.tsx index ea58ccbfa..6dccb8778 100644 --- a/src/Gang/ui/TerritorySubpage.tsx +++ b/src/Gang/ui/TerritorySubpage.tsx @@ -1,6 +1,3 @@ -/** - * React Component for the territory subpage. - */ import React, { useState } from "react"; import { Container, Button, Paper, Box, Tooltip, Switch, FormControlLabel, Typography } from "@mui/material"; @@ -14,6 +11,7 @@ import { AllGangs } from "../AllGangs"; import { useGang } from "./Context"; import { TerritoryInfoModal } from "./TerritoryInfoModal"; +/** React Component for the territory subpage. */ export function TerritorySubpage(): React.ReactElement { const gang = useGang(); const gangNames = Object.keys(AllGangs).filter((g) => g != gang.facName); diff --git a/src/Hacking.ts b/src/Hacking.ts index d0febe357..78308ecd9 100644 --- a/src/Hacking.ts +++ b/src/Hacking.ts @@ -3,9 +3,7 @@ import { Person } from "./PersonObjects/Person"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; import { Server } from "./Server/Server"; -/** - * Returns the chance the person has to successfully hack a server - */ +/** Returns the chance the person has to successfully hack a server */ export function calculateHackingChance(server: Server, person: Person): number { const hackFactor = 1.75; const difficultyMult = (100 - server.hackDifficulty) / 100; @@ -64,9 +62,7 @@ export function calculatePercentMoneyHacked(server: Server, person: Person): num return percentMoneyHacked; } -/** - * Returns time it takes to complete a hack on a server, in seconds - */ +/** Returns time it takes to complete a hack on a server, in seconds */ export function calculateHackingTime(server: Server, person: Person): number { const difficultyMult = server.requiredHackingSkill * server.hackDifficulty; @@ -85,18 +81,14 @@ export function calculateHackingTime(server: Server, person: Person): number { return hackingTime; } -/** - * Returns time it takes to complete a grow operation on a server, in seconds - */ +/** Returns time it takes to complete a grow operation on a server, in seconds */ export function calculateGrowTime(server: Server, person: Person): number { const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2 return growTimeMultiplier * calculateHackingTime(server, person); } -/** - * Returns time it takes to complete a weaken operation on a server, in seconds - */ +/** Returns time it takes to complete a weaken operation on a server, in seconds */ export function calculateWeakenTime(server: Server, person: Person): number { const weakenTimeMultiplier = 4; // Relative to hacking time diff --git a/src/Hacknet/HacknetNode.ts b/src/Hacknet/HacknetNode.ts index 4ba906f3e..c27b8e030 100644 --- a/src/Hacknet/HacknetNode.ts +++ b/src/Hacknet/HacknetNode.ts @@ -120,16 +120,12 @@ export class HacknetNode implements IHacknetNode { } } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("HacknetNode", this); } - /** - * Initiatizes a HacknetNode object from a JSON save state. - */ + /** Initiatizes a HacknetNode object from a JSON save state. */ static fromJSON(value: IReviverValue): HacknetNode { return Generic_fromJSON(HacknetNode, value.data); } diff --git a/src/Hacknet/HacknetServer.ts b/src/Hacknet/HacknetServer.ts index e2b005dd5..8bf2276ca 100644 --- a/src/Hacknet/HacknetServer.ts +++ b/src/Hacknet/HacknetServer.ts @@ -1,6 +1,3 @@ -/** - * Hacknet Servers - Reworked Hacknet Node mechanic for BitNode-9 - */ import { CONSTANTS } from "../Constants"; import { IHacknetNode } from "./IHacknetNode"; @@ -30,6 +27,7 @@ interface IConstructorParams { organizationName?: string; } +/** Hacknet Servers - Reworked Hacknet Node mechanic for BitNode-9 */ export class HacknetServer extends BaseServer implements IHacknetNode { // Cache level. Affects hash Capacity cache = 1; diff --git a/src/Hacknet/HashManager.ts b/src/Hacknet/HashManager.ts index 85d3ecd0a..48b5541f6 100644 --- a/src/Hacknet/HashManager.ts +++ b/src/Hacknet/HashManager.ts @@ -28,9 +28,7 @@ export class HashManager { } } - /** - * Generic helper function for getting a multiplier from a HashUpgrade - */ + /** Generic helper function for getting a multiplier from a HashUpgrade */ getMult(upgName: string): number { const upg = HashUpgrades[upgName]; const currLevel = this.upgrades[upgName]; @@ -42,18 +40,14 @@ export class HashManager { return 1 + (upg.value * currLevel) / 100; } - /** - * One of the Hash upgrades improves studying. This returns that multiplier - */ + /** One of the Hash upgrades improves studying. This returns that multiplier */ getStudyMult(): number { const upgName = "Improve Studying"; return this.getMult(upgName); } - /** - * One of the Hash upgrades improves gym training. This returns that multiplier - */ + /** One of the Hash upgrades improves gym training. This returns that multiplier */ getTrainingMult(): number { const upgName = "Improve Gym Training"; @@ -69,9 +63,7 @@ export class HashManager { return upg; } - /** - * Get the cost (in hashes) of an upgrade - */ + /** Get the cost (in hashes) of an upgrade */ getUpgradeCost(upgName: string, count = 1): number { const upg = this.getUpgrade(upgName); const currLevel = this.upgrades[upgName]; @@ -93,9 +85,7 @@ export class HashManager { this.updateCapacity(0); } - /** - * Reverts an upgrade and refunds the hashes used to buy it - */ + /** Reverts an upgrade and refunds the hashes used to buy it */ refundUpgrade(upgName: string, count = 1): void { const upg = HashUpgrades[upgName]; diff --git a/src/Hacknet/HashUpgrade.ts b/src/Hacknet/HashUpgrade.ts index 9f53f333a..5b6c14ae1 100644 --- a/src/Hacknet/HashUpgrade.ts +++ b/src/Hacknet/HashUpgrade.ts @@ -1,6 +1,4 @@ -/** - * Object representing an upgrade that can be purchased with hashes - */ +/** Object representing an upgrade that can be purchased with hashes */ export interface IConstructorParams { cost?: number; costPerLevel: number; @@ -26,9 +24,7 @@ export class HashUpgrade { */ costPerLevel = 0; - /** - * Description of what the upgrade does - */ + /** Description of what the upgrade does */ desc = ""; /** @@ -37,7 +33,7 @@ export class HashUpgrade { */ hasTargetServer = false; - // Name of upgrade + /** Name of upgrade */ name = ""; // Generic value used to indicate the potency/amount of this upgrade's effect diff --git a/src/Hacknet/ui/HacknetRoot.tsx b/src/Hacknet/ui/HacknetRoot.tsx index 16bb14612..028cd0833 100644 --- a/src/Hacknet/ui/HacknetRoot.tsx +++ b/src/Hacknet/ui/HacknetRoot.tsx @@ -1,6 +1,3 @@ -/** - * Root React Component for the Hacknet Node UI - */ import React, { useState, useEffect } from "react"; import { GeneralInfo } from "./GeneralInfo"; @@ -29,6 +26,7 @@ import Grid from "@mui/material/Grid"; import Button from "@mui/material/Button"; import { Box } from "@mui/material"; +/** Root React Component for the Hacknet Node UI */ export function HacknetRoot(): React.ReactElement { const [open, setOpen] = useState(false); const setRerender = useState(false)[1]; diff --git a/src/Hacknet/ui/HashUpgradeModal.tsx b/src/Hacknet/ui/HashUpgradeModal.tsx index 83c4d68c2..93ebb86ed 100644 --- a/src/Hacknet/ui/HashUpgradeModal.tsx +++ b/src/Hacknet/ui/HashUpgradeModal.tsx @@ -1,6 +1,3 @@ -/** - * Create the pop-up for purchasing upgrades with hashes - */ import React, { useState, useEffect } from "react"; import { HashUpgrades } from "../HashUpgrades"; @@ -16,6 +13,7 @@ interface IProps { onClose: () => void; } +/** Create the pop-up for purchasing upgrades with hashes */ export function HashUpgradeModal(props: IProps): React.ReactElement { const setRerender = useState(false)[1]; function rerender(): void { diff --git a/src/Hacknet/ui/PurchaseButton.tsx b/src/Hacknet/ui/PurchaseButton.tsx index 7d4c4a5f4..45bfb55a3 100644 --- a/src/Hacknet/ui/PurchaseButton.tsx +++ b/src/Hacknet/ui/PurchaseButton.tsx @@ -1,6 +1,3 @@ -/** - * React Component for the button that is used to purchase new Hacknet Nodes - */ import React from "react"; import { hasHacknetServers, hasMaxNumberHacknetServers } from "../HacknetHelpers"; @@ -15,6 +12,7 @@ interface IProps { cost: number; } +/** React Component for the button that is used to purchase new Hacknet Nodes */ export function PurchaseButton(props: IProps): React.ReactElement { const cost = props.cost; let text; diff --git a/src/Locations/City.ts b/src/Locations/City.ts index 089c0d869..44f69fa43 100644 --- a/src/Locations/City.ts +++ b/src/Locations/City.ts @@ -1,23 +1,15 @@ -/** - * Class representing a City in the game - */ import { CityName } from "./data/CityNames"; import { LocationName } from "./data/LocationNames"; +/** Class representing a City in the game */ export class City { - /** - * List of all locations in this city - */ + /** List of all locations in this city */ locations: LocationName[]; - /** - * Name of this city - */ + /** Name of this city */ name: CityName; - /** - * Metro map ascii art - */ + /** Metro map ascii art */ asciiArt: string; constructor(name: CityName, locations: LocationName[] = [], asciiArt = "") { diff --git a/src/Locations/Location.ts b/src/Locations/Location.ts index eaf06fecc..ae9ea5384 100644 --- a/src/Locations/Location.ts +++ b/src/Locations/Location.ts @@ -1,6 +1,3 @@ -/** - * Class representing a visitable location in the world - */ import { CityName } from "./data/CityNames"; import { LocationName } from "./data/LocationNames"; import { LocationType } from "./LocationTypeEnum"; @@ -21,6 +18,7 @@ export interface IConstructorParams { techVendorMinRam?: number; } +/** Class representing a visitable location in the world */ export class Location { /** * Name of city this location is in. If this property is null, it means this i @@ -28,14 +26,10 @@ export class Location { */ city: CityName | null = null; - /** - * Cost multiplier that influences how expensive a gym/university is - */ + /** Cost multiplier that influences how expensive a gym/university is */ costMult = 0; - /** - * Exp multiplier that influences how effective a gym/university is - */ + /** Exp multiplier that influences how effective a gym/university is */ expMult = 0; /** @@ -44,9 +38,7 @@ export class Location { */ infiltrationData?: IInfiltrationMetadata; - /** - * Identifier for location - */ + /** Identifier for location */ name: LocationName = LocationName.Void; /** diff --git a/src/Locations/LocationTypeEnum.ts b/src/Locations/LocationTypeEnum.ts index c5cdf9bbc..eb587f19a 100644 --- a/src/Locations/LocationTypeEnum.ts +++ b/src/Locations/LocationTypeEnum.ts @@ -1,6 +1,4 @@ -/** - * Enum defining the different types of possible locations - */ +/** Enum defining the different types of possible locations */ export enum LocationType { Company, Gym, diff --git a/src/Locations/data/LocationNames.ts b/src/Locations/data/LocationNames.ts index 4a8efdc44..abb02befa 100644 --- a/src/Locations/data/LocationNames.ts +++ b/src/Locations/data/LocationNames.ts @@ -1,6 +1,4 @@ -/** - * Names of all locations - */ +/** Names of all locations */ export enum LocationName { // Aevum Locations AevumAeroCorp = "AeroCorp", diff --git a/src/Locations/ui/ApplyToJobButton.tsx b/src/Locations/ui/ApplyToJobButton.tsx index 0441c6e07..f1055c492 100644 --- a/src/Locations/ui/ApplyToJobButton.tsx +++ b/src/Locations/ui/ApplyToJobButton.tsx @@ -1,6 +1,3 @@ -/** - * React Component for a button that's used to apply for a job - */ import * as React from "react"; import { Company } from "../../Company/Company"; @@ -18,6 +15,7 @@ type IProps = { text: string; }; +/** React Component for a button that's used to apply for a job */ export function ApplyToJobButton(props: IProps): React.ReactElement { function getJobRequirementTooltip(): string { const pos = Player.getNextCompanyPosition(props.company, props.entryPosType); diff --git a/src/Locations/ui/CompanyLocation.tsx b/src/Locations/ui/CompanyLocation.tsx index 13a125df8..78608acc9 100644 --- a/src/Locations/ui/CompanyLocation.tsx +++ b/src/Locations/ui/CompanyLocation.tsx @@ -47,17 +47,13 @@ export function CompanyLocation(props: IProps): React.ReactElement { const company = Companies[props.locName]; if (company == null) throw new Error(`CompanyLocation component constructed with invalid company: ${props.locName}`); - /** - * Reference to the Location that this component is being rendered for - */ + /** Reference to the Location that this component is being rendered for */ const location = Locations[props.locName]; if (location == null) { throw new Error(`CompanyLocation component constructed with invalid location: ${props.locName}`); } - /** - * Name of company position that player holds, if applicable - */ + /** Name of company position that player holds, if applicable */ const jobTitle = Player.jobs[props.locName] ? Player.jobs[props.locName] : null; /** diff --git a/src/Locations/ui/HospitalLocation.tsx b/src/Locations/ui/HospitalLocation.tsx index 1268f621a..e3a6e5478 100644 --- a/src/Locations/ui/HospitalLocation.tsx +++ b/src/Locations/ui/HospitalLocation.tsx @@ -19,9 +19,7 @@ type IState = { //Todo: Make this a functional component export class HospitalLocation extends React.Component, IState> { - /** - * Stores button styling that sets them all to block display - */ + /** Stores button styling that sets them all to block display */ btnStyle = { display: "block" }; constructor() { diff --git a/src/Locations/ui/PurchaseServerModal.tsx b/src/Locations/ui/PurchaseServerModal.tsx index 60b1853d4..4962f2a3b 100644 --- a/src/Locations/ui/PurchaseServerModal.tsx +++ b/src/Locations/ui/PurchaseServerModal.tsx @@ -1,6 +1,3 @@ -/** - * React Component for the popup used to purchase a new server. - */ import React, { useState } from "react"; import { purchaseServer } from "../../Server/ServerPurchases"; import { numeralWrapper } from "../../ui/numeralFormat"; @@ -20,6 +17,7 @@ interface IProps { rerender: () => void; } +/** React Component for the popup used to purchase a new server. */ export function PurchaseServerModal(props: IProps): React.ReactElement { const [hostname, setHostname] = useState(""); diff --git a/src/Locations/ui/SpecialLocation.tsx b/src/Locations/ui/SpecialLocation.tsx index e003cd1f7..3c0d5ede1 100644 --- a/src/Locations/ui/SpecialLocation.tsx +++ b/src/Locations/ui/SpecialLocation.tsx @@ -25,7 +25,7 @@ import { Router } from "../../ui/GameRoot"; import { Player } from "../../Player"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; -import { SnackbarEvents } from "../../ui/React/Snackbar"; +import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; import { N00dles } from "../../utils/helpers/N00dles"; import { Exploit } from "../../Exploits/Exploit"; import { applyAugmentation } from "../../Augmentation/AugmentationHelpers"; @@ -45,9 +45,7 @@ export function SpecialLocation(props: IProps): React.ReactElement { const setRerender = useState(false)[1]; const inBladeburner = Player.inBladeburner(); - /** - * Click handler for Bladeburner button at Sector-12 NSA - */ + /** Click handler for Bladeburner button at Sector-12 NSA */ function handleBladeburner(): void { if (Player.inBladeburner()) { // Enter Bladeburner division @@ -73,9 +71,7 @@ export function SpecialLocation(props: IProps): React.ReactElement { } } - /** - * Click handler for Resleeving button at New Tokyo VitaLife - */ + /** Click handler for Resleeving button at New Tokyo VitaLife */ function handleGrafting(): void { Router.toGrafting(); } @@ -95,7 +91,7 @@ export function SpecialLocation(props: IProps): React.ReactElement { function renderNoodleBar(): React.ReactElement { function EatNoodles(): void { - SnackbarEvents.emit("You ate some delicious noodles and feel refreshed", "success", 2000); + SnackbarEvents.emit("You ate some delicious noodles and feel refreshed", ToastVariant.SUCCESS, 2000); N00dles(); // This is the true power of the noodles. if (Player.sourceFiles.length > 0) Player.giveExploit(Exploit.N00dles); if (Player.sourceFileLvl(5) > 0 || Player.bitNodeN === 5) { diff --git a/src/Locations/ui/TorButton.tsx b/src/Locations/ui/TorButton.tsx index 80e69671f..63c94a797 100644 --- a/src/Locations/ui/TorButton.tsx +++ b/src/Locations/ui/TorButton.tsx @@ -10,9 +10,7 @@ import { Player } from "../../Player"; import { Money } from "../../ui/React/Money"; -/** - * Attempt to purchase a TOR router using the button. - */ +/** Attempt to purchase a TOR router using the button. */ export function purchaseTorRouter(): void { if (Player.hasTorRouter()) { dialogBoxCreate(`You already have a TOR Router!`); diff --git a/src/Netscript/Environment.ts b/src/Netscript/Environment.ts index 6985ec043..3bb24bc7a 100644 --- a/src/Netscript/Environment.ts +++ b/src/Netscript/Environment.ts @@ -5,19 +5,13 @@ import { NS } from "../ScriptEditor/NetscriptDefinitions"; * Netscript functions and arguments for that script. */ export class Environment { - /** - * Whether or not the script that uses this Environment should stop running - */ + /** Whether or not the script that uses this Environment should stop running */ stopFlag = false; - /** - * The currently running function - */ + /** The currently running function */ runningFn = ""; - /** - * Environment variables (currently only Netscript functions) - */ + /** Environment variables (currently only Netscript functions) */ vars: NS | null = null; } diff --git a/src/Netscript/Pid.ts b/src/Netscript/Pid.ts index 77c5db17c..cd236518b 100644 --- a/src/Netscript/Pid.ts +++ b/src/Netscript/Pid.ts @@ -2,9 +2,7 @@ import { workerScripts } from "./WorkerScripts"; let pidCounter = 1; -/** - * Find and return the next availble PID for a script - */ +/** Find and return the next availble PID for a script */ export function generateNextPid(): number { let tempCounter = pidCounter; diff --git a/src/Netscript/WorkerScript.ts b/src/Netscript/WorkerScript.ts index 238b0be43..ff9ad4d99 100644 --- a/src/Netscript/WorkerScript.ts +++ b/src/Netscript/WorkerScript.ts @@ -18,14 +18,10 @@ import { ScriptDeath } from "./ScriptDeath"; import { ScriptArg } from "./ScriptArg"; export class WorkerScript { - /** - * Script's arguments - */ + /** Script's arguments */ args: ScriptArg[]; - /** - * Copy of the script's code - */ + /** Copy of the script's code */ code = ""; /** @@ -34,14 +30,10 @@ export class WorkerScript { */ delay: number | null = null; - /** - * Holds the Promise reject() function while the script is "blocked" by an async op - */ + /** Holds the Promise reject() function while the script is "blocked" by an async op */ delayReject?: (reason?: ScriptDeath) => void; - /** - * Stores names of all functions that have logging disabled - */ + /** Stores names of all functions that have logging disabled */ disableLogs: Record = {}; /** @@ -51,19 +43,13 @@ export class WorkerScript { */ dynamicLoadedFns: Record = {}; - /** - * Tracks dynamic RAM usage - */ + /** Tracks dynamic RAM usage */ dynamicRamUsage: number = RamCostConstants.ScriptBaseRamCost; - /** - * Netscript Environment for this script - */ + /** Netscript Environment for this script */ env: Environment; - /** - * Status message in case of script error. - */ + /** Status message in case of script error. */ errorMessage = ""; /** @@ -72,14 +58,10 @@ export class WorkerScript { */ loadedFns: Record = {}; - /** - * Filename of script - */ + /** Filename of script */ name: string; - /** - * Script's output/return value. Currently not used or implemented - */ + /** Script's output/return value. Currently not used or implemented */ output = ""; /** @@ -88,24 +70,16 @@ export class WorkerScript { */ pid: number; - /** - * Script's Static RAM usage. Equivalent to underlying script's RAM usage - */ + /** Script's Static RAM usage. Equivalent to underlying script's RAM usage */ ramUsage = 0; - /** - * Reference to underlying RunningScript object - */ + /** Reference to underlying RunningScript object */ scriptRef: RunningScript; - /** - * hostname on which this script is running - */ + /** hostname on which this script is running */ hostname: string; - /** - * Function called when the script ends. - */ + /** Function called when the script ends. */ atExit?: () => void; constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => NS) { @@ -142,9 +116,7 @@ export class WorkerScript { } } - /** - * Returns the Server on which this script is running - */ + /** Returns the Server on which this script is running */ getServer(): BaseServer { const server = GetServer(this.hostname); if (server == null) throw new Error(`Script ${this.name} pid ${this.pid} is running on non-existent server?`); diff --git a/src/Netscript/WorkerScriptStartStopEventEmitter.ts b/src/Netscript/WorkerScriptStartStopEventEmitter.ts index ac1c2ad2b..45a703fdc 100644 --- a/src/Netscript/WorkerScriptStartStopEventEmitter.ts +++ b/src/Netscript/WorkerScriptStartStopEventEmitter.ts @@ -1,6 +1,4 @@ -/** - * Event emitter that triggers when scripts are started/stopped - */ import { EventEmitter } from "../utils/EventEmitter"; +/** Event emitter that triggers when scripts are started/stopped */ export const WorkerScriptStartStopEventEmitter = new EventEmitter<[]>(); diff --git a/src/Netscript/WorkerScripts.ts b/src/Netscript/WorkerScripts.ts index 58c184314..24008cffe 100644 --- a/src/Netscript/WorkerScripts.ts +++ b/src/Netscript/WorkerScripts.ts @@ -1,6 +1,4 @@ -/** - * Global pool of all active scripts (scripts that are currently running) - */ import { WorkerScript } from "./WorkerScript"; +/** Global pool of all active scripts (scripts that are currently running) */ export const workerScripts: Map = new Map(); diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index c15235c54..201c4a154 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -80,17 +80,11 @@ import { recentScripts } from "./Netscript/RecentScripts"; import { InternalAPI, NetscriptContext, wrapAPI } from "./Netscript/APIWrapper"; import { INetscriptExtra } from "./NetscriptFunctions/Extra"; import { ScriptDeath } from "./Netscript/ScriptDeath"; -import { TypeEquality, ValuesFrom } from "./types"; // "Enums" as object export const enums = { - toast: { - SUCCESS: "success", - WARNING: "warning", - ERROR: "error", - INFO: "info", - } as const, -}; + toast: ToastVariant, +} as const; export type NSFull = NS & INetscriptExtra; export function NetscriptFunctions(workerScript: WorkerScript): NSFull { @@ -1796,7 +1790,7 @@ const base: InternalAPI = { const duration = _duration === null ? null : helpers.number(ctx, "duration", _duration); if (!checkObjContainsValue(enums.toast, variant)) throw new Error(`variant must be one of ${Object.values(enums.toast).join(", ")}`); - SnackbarEvents.emit(message, variant, duration); + SnackbarEvents.emit(message, variant as ToastVariant, duration); }, prompt: (ctx: NetscriptContext) => diff --git a/src/NetscriptFunctions/StockMarket.ts b/src/NetscriptFunctions/StockMarket.ts index 7d0712e22..273ec8a24 100644 --- a/src/NetscriptFunctions/StockMarket.ts +++ b/src/NetscriptFunctions/StockMarket.ts @@ -17,9 +17,7 @@ import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { helpers } from "../Netscript/NetscriptHelpers"; export function NetscriptStockMarket(): InternalAPI { - /** - * Checks if the player has TIX API access. Throws an error if the player does not - */ + /** Checks if the player has TIX API access. Throws an error if the player does not */ const checkTixApiAccess = function (ctx: NetscriptContext): void { if (!player.hasWseAccount) { throw helpers.makeRuntimeErrorMsg(ctx, `You don't have WSE Access! Cannot use ${ctx.function}()`); diff --git a/src/NetscriptWorker.ts b/src/NetscriptWorker.ts index a69548656..a0a6f992f 100644 --- a/src/NetscriptWorker.ts +++ b/src/NetscriptWorker.ts @@ -354,9 +354,7 @@ function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseS return true; } -/** - * Updates the online running time stat of all running scripts - */ +/** Updates the online running time stat of all running scripts */ export function updateOnlineScriptTimes(numCycles = 1): void { const time = (numCycles * CONSTANTS._idleSpeed) / 1000; //seconds for (const ws of workerScripts.values()) { @@ -404,9 +402,7 @@ export function loadAllRunningScripts(): void { } } -/** - * Run a script from inside another script (run(), exec(), spawn(), etc.) - */ +/** Run a script from inside another script (run(), exec(), spawn(), etc.) */ export function runScriptFromScript( caller: string, server: BaseServer, diff --git a/src/PersonObjects/Player/PlayerObject.ts b/src/PersonObjects/Player/PlayerObject.ts index faa16699d..49fb2cf28 100644 --- a/src/PersonObjects/Player/PlayerObject.ts +++ b/src/PersonObjects/Player/PlayerObject.ts @@ -159,16 +159,12 @@ export class PlayerObject extends Person { return "Player"; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("PlayerObject", this); } - /** - * Initiatizes a PlayerObject object from a JSON save state. - */ + /** Initiatizes a PlayerObject object from a JSON save state. */ static fromJSON(value: IReviverValue): PlayerObject { return Generic_fromJSON(PlayerObject, value.data); } diff --git a/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts b/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts index a5da1c307..e116e5240 100644 --- a/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectAugmentationMethods.ts @@ -1,6 +1,4 @@ -/** - * Augmentation-related methods for the Player class (PlayerObject) - */ +/** Augmentation-related methods for the Player class (PlayerObject) */ import { PlayerObject } from "./PlayerObject"; import { calculateEntropy } from "../Grafting/EntropyAccumulation"; diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts index bc378cfa9..3cc2e46d4 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts @@ -39,7 +39,7 @@ import { numeralWrapper } from "../../ui/numeralFormat"; import { MoneySourceTracker } from "../../utils/MoneySourceTracker"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; -import { SnackbarEvents } from "../../ui/React/Snackbar"; +import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; import { achievements } from "../../Achievements/Achievements"; import { FactionNames } from "../../Faction/data/FactionNames"; @@ -257,7 +257,7 @@ export function takeDamage(this: PlayerObject, amt: number): boolean { export function hospitalize(this: PlayerObject): number { const cost = getHospitalizationCost(); - SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, "warning", 2000); + SnackbarEvents.emit(`You've been Hospitalized for ${numeralWrapper.formatMoney(cost)}`, ToastVariant.SUCCESS, 2000); this.loseMoney(cost, "hospitalization"); this.hp.current = this.hp.max; @@ -1193,7 +1193,7 @@ export function canAccessGrafting(this: PlayerObject): boolean { export function giveExploit(this: PlayerObject, exploit: Exploit): void { if (!this.exploits.includes(exploit)) { this.exploits.push(exploit); - SnackbarEvents.emit("SF -1 acquired!", "success", 2000); + SnackbarEvents.emit("SF -1 acquired!", ToastVariant.SUCCESS, 2000); } } @@ -1202,7 +1202,7 @@ export function giveAchievement(this: PlayerObject, achievementId: string): void if (!achievement) return; if (!this.achievements.map((a) => a.ID).includes(achievementId)) { this.achievements.push({ ID: achievementId, unlockedOn: new Date().getTime() }); - SnackbarEvents.emit(`Unlocked Achievement: "${achievement.Name}"`, "success", 2000); + SnackbarEvents.emit(`Unlocked Achievement: "${achievement.Name}"`, ToastVariant.SUCCESS, 2000); } } diff --git a/src/PersonObjects/Player/PlayerObjectServerMethods.ts b/src/PersonObjects/Player/PlayerObjectServerMethods.ts index a8ff2c456..ea991401c 100644 --- a/src/PersonObjects/Player/PlayerObjectServerMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectServerMethods.ts @@ -1,6 +1,4 @@ -/** - * Server and HacknetServer-related methods for the Player class (PlayerObject) - */ +// Server and HacknetServer-related methods for the Player class (PlayerObject) import { PlayerObject } from "./PlayerObject"; import { CONSTANTS } from "../../Constants"; diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts index aa934b705..574337e47 100644 --- a/src/PersonObjects/Sleeve/Sleeve.ts +++ b/src/PersonObjects/Sleeve/Sleeve.ts @@ -48,9 +48,7 @@ import * as sleeveMethods from "./SleeveMethods"; export class Sleeve extends Person { currentWork: Work | null = null; - /** - * Clone retains 'memory' synchronization (and maybe exp?) upon prestige/installing Augs - */ + /** Clone retains 'memory' synchronization (and maybe exp?) upon prestige/installing Augs */ memory = 1; /** @@ -62,9 +60,7 @@ export class Sleeve extends Person { */ shock = 1; - /** - * Stored number of game "loop" cycles - */ + /** Stored number of game "loop" cycles */ storedCycles = 0; /** @@ -100,9 +96,7 @@ export class Sleeve extends Person { this.currentWork = null; } - /** - * Commit crimes - */ + /** Commit crimes */ commitCrime(crimeKey: string): boolean { const crime: Crime | null = Crimes[crimeKey] || Object.values(Crimes).find((crime) => crime.name === crimeKey); if (!crime) { @@ -113,9 +107,7 @@ export class Sleeve extends Person { return true; } - /** - * Returns the cost of upgrading this sleeve's memory by a certain amount - */ + /** Returns the cost of upgrading this sleeve's memory by a certain amount */ getMemoryUpgradeCost(n: number): number { const amt = Math.round(n); if (amt < 0) { @@ -150,9 +142,7 @@ export class Sleeve extends Person { this.updateSkillLevels(); } - /** - * Called on every sleeve for a Source File Prestige - */ + /** Called on every sleeve for a Source File Prestige */ prestige(): void { // Reset exp this.exp.hacking = 0; @@ -211,9 +201,7 @@ export class Sleeve extends Person { return true; } - /** - * Take a course at a university - */ + /** Take a course at a university */ takeUniversityCourse(universityName: string, className: string): boolean { // Set exp/money multipliers based on which university. // Also check that the sleeve is in the right city @@ -270,9 +258,7 @@ export class Sleeve extends Person { return true; } - /** - * Travel to another City. Costs money from player - */ + /** Travel to another City. Costs money from player */ travel(newCity: CityName): boolean { Player.loseMoney(CONSTANTS.TravelCost, "sleeves"); this.city = newCity; @@ -354,9 +340,7 @@ export class Sleeve extends Person { return true; } - /** - * Begin a gym workout task - */ + /** Begin a gym workout task */ workoutAtGym(gymName: string, stat: string): boolean { // Set exp/money multipliers based on which university. // Also check that the sleeve is in the right city @@ -420,9 +404,7 @@ export class Sleeve extends Person { return true; } - /** - * Begin a bladeburner task - */ + /** Begin a bladeburner task */ bladeburner(action: string, contract: string): boolean { if (!Player.bladeburner) return false; switch (action) { @@ -495,16 +477,12 @@ export class Sleeve extends Person { return "Sleeve"; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("Sleeve", this); } - /** - * Initiatizes a Sleeve object from a JSON save state. - */ + /** Initiatizes a Sleeve object from a JSON save state. */ static fromJSON(value: IReviverValue): Sleeve { return Generic_fromJSON(Sleeve, value.data); } diff --git a/src/PersonObjects/Sleeve/SleeveMethods.ts b/src/PersonObjects/Sleeve/SleeveMethods.ts index 2009da2f7..ae2da0958 100644 --- a/src/PersonObjects/Sleeve/SleeveMethods.ts +++ b/src/PersonObjects/Sleeve/SleeveMethods.ts @@ -10,9 +10,7 @@ import { mergeMultipliers, Multipliers } from "../Multipliers"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; import { getFactionAugmentationsFiltered } from "../../Faction/FactionHelpers"; -/** - * Updates this object's multipliers for the given augmentation - */ +/** Updates this object's multipliers for the given augmentation */ export function applyAugmentation(this: Sleeve, aug: Augmentation): void { this.mults = mergeMultipliers(this.mults, aug.mults); } diff --git a/src/PersonObjects/Sleeve/SleeveTaskTypesEnum.ts b/src/PersonObjects/Sleeve/SleeveTaskTypesEnum.ts index 68881383f..ab8cffd19 100644 --- a/src/PersonObjects/Sleeve/SleeveTaskTypesEnum.ts +++ b/src/PersonObjects/Sleeve/SleeveTaskTypesEnum.ts @@ -1,6 +1,4 @@ -/** - * Enum for different types of tasks that a Sleeve can perform - */ +/** Enum for different types of tasks that a Sleeve can perform */ export enum SleeveTaskType { // Same Order as selectable order in UI Idle, diff --git a/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts b/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts index cd4de69de..4a5bf96bd 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveBladeburnerWork.ts @@ -75,16 +75,12 @@ export class SleeveBladeburnerWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("SleeveBladeburnerWork", this); } - /** - * Initiatizes a BladeburnerWork object from a JSON save state. - */ + /** Initiatizes a BladeburnerWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveBladeburnerWork { return Generic_fromJSON(SleeveBladeburnerWork, value.data); } diff --git a/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts b/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts index 1b59b78fb..ae5fac113 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts @@ -45,16 +45,12 @@ export class SleeveClassWork extends Work { location: this.location, }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("SleeveClassWork", this); } - /** - * Initiatizes a ClassWork object from a JSON save state. - */ + /** Initiatizes a ClassWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveClassWork { return Generic_fromJSON(SleeveClassWork, value.data); } diff --git a/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts b/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts index a3a53e5a3..a83967941 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveCompanyWork.ts @@ -49,16 +49,12 @@ export class SleeveCompanyWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("SleeveCompanyWork", this); } - /** - * Initiatizes a CompanyWork object from a JSON save state. - */ + /** Initiatizes a CompanyWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveCompanyWork { return Generic_fromJSON(SleeveCompanyWork, value.data); } diff --git a/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts index 75d315452..fe2c56202 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts @@ -68,16 +68,12 @@ export class SleeveCrimeWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("SleeveCrimeWork", this); } - /** - * Initiatizes a RecoveryWork object from a JSON save state. - */ + /** Initiatizes a RecoveryWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveCrimeWork { return Generic_fromJSON(SleeveCrimeWork, value.data); } diff --git a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts index d4df44ba5..0d4711afc 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts @@ -78,16 +78,12 @@ export class SleeveFactionWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("SleeveFactionWork", this); } - /** - * Initiatizes a FactionWork object from a JSON save state. - */ + /** Initiatizes a FactionWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveFactionWork { return Generic_fromJSON(SleeveFactionWork, value.data); } diff --git a/src/PersonObjects/Sleeve/Work/SleeveInfiltrateWork.ts b/src/PersonObjects/Sleeve/Work/SleeveInfiltrateWork.ts index d0cf4f217..604b9d310 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveInfiltrateWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveInfiltrateWork.ts @@ -36,16 +36,12 @@ export class SleeveInfiltrateWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("SleeveInfiltrateWork", this); } - /** - * Initiatizes a BladeburnerWork object from a JSON save state. - */ + /** Initiatizes a BladeburnerWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveInfiltrateWork { return Generic_fromJSON(SleeveInfiltrateWork, value.data); } diff --git a/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts b/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts index 98707b6fc..3a6b7bea2 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveRecoveryWork.ts @@ -22,16 +22,12 @@ export class SleeveRecoveryWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("SleeveRecoveryWork", this); } - /** - * Initiatizes a RecoveryWork object from a JSON save state. - */ + /** Initiatizes a RecoveryWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveRecoveryWork { return Generic_fromJSON(SleeveRecoveryWork, value.data); } diff --git a/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts b/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts index 86d34184a..1ce2b665c 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveSupportWork.ts @@ -25,16 +25,12 @@ export class SleeveSupportWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("SleeveSupportWork", this); } - /** - * Initiatizes a BladeburnerWork object from a JSON save state. - */ + /** Initiatizes a BladeburnerWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveSupportWork { return Generic_fromJSON(SleeveSupportWork, value.data); } diff --git a/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts b/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts index 54d52fe56..1025fb3bf 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveSynchroWork.ts @@ -23,16 +23,12 @@ export class SleeveSynchroWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("SleeveSynchroWork", this); } - /** - * Initiatizes a SynchroWork object from a JSON save state. - */ + /** Initiatizes a SynchroWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveSynchroWork { return Generic_fromJSON(SleeveSynchroWork, value.data); } diff --git a/src/PersonObjects/Sleeve/ui/CovenantPurchasesRoot.tsx b/src/PersonObjects/Sleeve/ui/CovenantPurchasesRoot.tsx index c3030a06e..2b1baf7ae 100644 --- a/src/PersonObjects/Sleeve/ui/CovenantPurchasesRoot.tsx +++ b/src/PersonObjects/Sleeve/ui/CovenantPurchasesRoot.tsx @@ -26,16 +26,12 @@ interface IProps { export function CovenantPurchasesRoot(props: IProps): React.ReactElement { const [update, setUpdate] = useState(0); - /** - * Get the cost to purchase a new Duplicate Sleeve - */ + /** Get the cost to purchase a new Duplicate Sleeve */ function purchaseCost(): number { return Math.pow(10, Player.sleevesFromCovenant) * BaseCostPerSleeve; } - /** - * Force a rerender by just changing an arbitrary state value - */ + /** Force a rerender by just changing an arbitrary state value */ function rerender(): void { setUpdate(update + 1); } diff --git a/src/RedPill.tsx b/src/RedPill.tsx index 0bcd7a054..a1b8ea13e 100644 --- a/src/RedPill.tsx +++ b/src/RedPill.tsx @@ -1,6 +1,4 @@ -/** - * Implementation for what happens when you destroy a BitNode - */ +/** Implementation for what happens when you destroy a BitNode */ import React from "react"; import { Player } from "./Player"; import { prestigeSourceFile } from "./Prestige"; @@ -19,17 +17,9 @@ function giveSourceFile(bitNodeNumber: number): void { } // Check if player already has this source file - let alreadyOwned = false; - let ownedSourceFile = null; - for (let i = 0; i < Player.sourceFiles.length; ++i) { - if (Player.sourceFiles[i].n === bitNodeNumber) { - alreadyOwned = true; - ownedSourceFile = Player.sourceFiles[i]; - break; - } - } + const ownedSourceFile = Player.sourceFiles.find(sourceFile=>sourceFile.n === bitNodeNumber) - if (alreadyOwned && ownedSourceFile) { + if (ownedSourceFile) { if (ownedSourceFile.lvl >= 3 && ownedSourceFile.n !== 12) { dialogBoxCreate( `The Source-File for the BitNode you just destroyed, ${sourceFile.name}, is already at max level!`, @@ -45,10 +35,9 @@ function giveSourceFile(bitNodeNumber: number): void { ); } } else { - const playerSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1); - Player.sourceFiles.push(playerSrcFile); + const newSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1); + Player.sourceFiles.push(newSrcFile); if (bitNodeNumber === 5 && Player.skills.intelligence === 0) { - // Artificial Intelligence Player.skills.intelligence = 1; } dialogBoxCreate( diff --git a/src/RemoteFileAPI/Remote.ts b/src/RemoteFileAPI/Remote.ts index 5a5806a65..ed83fbc21 100644 --- a/src/RemoteFileAPI/Remote.ts +++ b/src/RemoteFileAPI/Remote.ts @@ -1,6 +1,6 @@ import { RFAMessage } from "./MessageDefinitions"; import { RFARequestHandler } from "./MessageHandlers"; -import { SnackbarEvents } from "../ui/React/Snackbar"; +import { SnackbarEvents, ToastVariant } from "../ui/React/Snackbar"; export class Remote { connection?: WebSocket; @@ -22,18 +22,18 @@ export class Remote { this.connection = new WebSocket(address); this.connection.addEventListener("error", (e: Event) => - SnackbarEvents.emit(`Error with websocket ${address}, details: ${JSON.stringify(e)}`, "error", 5000), + SnackbarEvents.emit(`Error with websocket ${address}, details: ${JSON.stringify(e)}`, ToastVariant.ERROR, 5000), ); this.connection.addEventListener("message", handleMessageEvent); this.connection.addEventListener("open", () => SnackbarEvents.emit( `Remote API connection established on ${this.ipaddr}:${this.port}`, - "success", + ToastVariant.SUCCESS, 2000, ), ); this.connection.addEventListener("close", () => - SnackbarEvents.emit("Remote API connection closed", "warning", 2000), + SnackbarEvents.emit("Remote API connection closed", ToastVariant.WARNING, 2000), ); } } diff --git a/src/SaveObject.tsx b/src/SaveObject.tsx index 9b1c47faf..14120faa1 100755 --- a/src/SaveObject.tsx +++ b/src/SaveObject.tsx @@ -16,7 +16,7 @@ import { Settings } from "./Settings/Settings"; import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket"; import { staneksGift, loadStaneksGift } from "./CotMG/Helper"; -import { SnackbarEvents } from "./ui/React/Snackbar"; +import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; import * as ExportBonus from "./ExportBonus"; @@ -120,7 +120,7 @@ class BitburnerSaveObject { pushGameSaved(saveData); if (emitToastEvent) { - SnackbarEvents.emit("Game Saved!", "info", 2000); + SnackbarEvents.emit("Game Saved!", ToastVariant.INFO, 2000); } return resolve(); }) diff --git a/src/Script/Script.ts b/src/Script/Script.ts index a28b81634..833b65229 100644 --- a/src/Script/Script.ts +++ b/src/Script/Script.ts @@ -61,9 +61,7 @@ export class Script { } } - /** - * Download the script as a file - */ + /** Download the script as a file */ download(): void { const filename = this.filename; const file = new Blob([this.code], { type: "text/plain" }); diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index a6efb5bd4..e09ba697b 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -1,14 +1,12 @@ -/** - * @public - */ +export type ValuesFrom = T[keyof T]; + +/** @public */ export interface HP { current: number; max: number; } -/** - * @public - */ +/** @public */ export interface Skills { hacking: number; strength: number; @@ -19,9 +17,7 @@ export interface Skills { intelligence: number; } -/** - * @public - */ +/** @public */ export interface PossibleInfiltrationLocation { city: string; name: string; @@ -33,24 +29,16 @@ export interface PossibleInfiltrationLocation { */ type CodingContractData = any; -/** - * @public - */ +/** @public */ type PortData = string | number; -/** - * @public - */ +/** @public */ type ScriptArg = string | number | boolean; -/** - * @public - */ +/** @public */ type FilenameOrPID = number | string; -/** - * @public - */ +/** @public */ interface Player { hp: HP; skills: Skills; @@ -72,9 +60,7 @@ interface Player { entropy: number; } -/** - * @public - */ +/** @public */ export interface Multipliers { /** Multiplier to hacking skill */ hacking?: number; @@ -138,9 +124,7 @@ export interface Multipliers { bladeburner_success_chance?: number; } -/** - * @public - */ +/** @public */ export interface RunningScript { /** Arguments the script was called with */ args: (string | number | boolean)[]; @@ -173,9 +157,7 @@ export interface RunningScript { threads: number; } -/** - * @public - */ +/** @public */ export interface RecentScript extends RunningScript { /** Timestamp of when the script was killed */ timeOfDeath: Date; @@ -259,17 +241,13 @@ export interface AugmentPair { cost: number; } -/** - * @public - */ +/** @public */ export enum PositionTypes { Long = "L", Short = "S", } -/** - * @public - */ +/** @public */ export enum OrderTypes { LimitBuy = "Limit Buy Order", LimitSell = "Limit Sell Order", @@ -633,9 +611,7 @@ export interface NodeStats { totalProduction: number; } -/** - * @public - */ +/** @public */ export interface CharacterMult { /** Agility stat */ agility: number; @@ -673,9 +649,7 @@ export interface CharacterMult { workMoney: number; } -/** - * @public - */ +/** @public */ export interface SleeveWorkGains { /** Hacking exp gained from work */ workHackExpGain: number; @@ -693,9 +667,7 @@ export interface SleeveWorkGains { workMoneyGain: number; } -/** - * @public - */ +/** @public */ export interface SourceFileLvl { /** The number of the source file */ n: number; @@ -745,9 +717,7 @@ export interface GangGenInfo { wantedPenalty: number; } -/** - * @public - */ +/** @public */ export interface GangOtherInfoObject { /** Gang power */ power: number; @@ -755,9 +725,7 @@ export interface GangOtherInfoObject { territory: number; } -/** - * @public - */ +/** @public */ export interface GangOtherInfo { [key: string]: GangOtherInfoObject; } @@ -818,9 +786,7 @@ export interface EquipmentStats { hack?: number; } -/** - * @public - */ +/** @public */ export interface GangTerritory { /** Money gain impact on task scaling */ money: number; @@ -830,9 +796,7 @@ export interface GangTerritory { wanted: number; } -/** - * @public - */ +/** @public */ export interface GangMemberInfo { /** Name of the gang member */ name: string; @@ -913,9 +877,7 @@ export interface GangMemberInfo { moneyGain: number; } -/** - * @public - */ +/** @public */ export interface GangMemberAscension { /** Amount of respect lost from ascending */ respect: number; @@ -3840,9 +3802,7 @@ interface SkillsFormulas { calculateExp(skill: number, skillMult?: number): number; } -/** - * @public - */ +/** @public */ export interface WorkStats { money: number; reputation: number; @@ -4152,9 +4112,7 @@ export interface Formulas { work: WorkFormulas; } -/** - * @public - */ +/** @public */ export interface Fragment { id: number; shape: boolean[][]; @@ -4163,9 +4121,7 @@ export interface Fragment { limit: number; } -/** - * @public - */ +/** @public */ export interface ActiveFragment { id: number; highestCharge: number; @@ -4287,26 +4243,20 @@ interface Stanek { acceptGift(): boolean; } -/** - * @public - */ +/** @public */ export interface InfiltrationReward { tradeRep: number; sellCash: number; SoARep: number; } -/** - * @public - */ +/** @public */ export interface ILocation { city: string; name: string; } -/** - * @public - */ +/** @public */ export interface InfiltrationLocation { location: ILocation; reward: InfiltrationReward; @@ -6385,7 +6335,7 @@ export interface NS { * @param variant - Type of toast, must be one of success, info, warning, error. Defaults to success. * @param duration - Duration of toast in ms. Can also be `null` to create a persistent toast. Defaults to 2000 */ - toast(msg: string, variant?: ToastVariantValues, duration?: number | null): void; + toast(msg: string, variant?: ToastVariant, duration?: number | null): void; /** * Download a file from the internet. @@ -6573,7 +6523,7 @@ export interface NS { enums: NSEnums; } -export const enums = { +declare const enums = { toast: { SUCCESS: "success", WARNING: "warning", @@ -6581,12 +6531,14 @@ export const enums = { INFO: "info", }, } as const; +type ToastVariant = ValuesFrom; + export type NSEnums = typeof enums; /** * Corporation Office API * @remarks - * Requires the Office API upgrade from your corporation. + * requires the Office API upgrade from your corporation. * @public */ export interface OfficeAPI { diff --git a/src/Server/BaseServer.ts b/src/Server/BaseServer.ts index 6ba4b96c8..6a2bcfbf7 100644 --- a/src/Server/BaseServer.ts +++ b/src/Server/BaseServer.ts @@ -1,6 +1,3 @@ -/** - * Abstract Base Class for any Server object - */ import { CodingContract } from "../CodingContracts"; import { RunningScript } from "../Script/RunningScript"; import { Script } from "../Script/Script"; @@ -28,7 +25,8 @@ interface writeResult { overwritten: boolean; } -export class BaseServer { +/** Abstract Base Class for any Server object */ +export abstract class BaseServer { // Coding Contract files on this server contracts: CodingContract[] = []; @@ -150,9 +148,7 @@ export class BaseServer { return null; } - /** - * Returns boolean indicating whether the given script is running on this server - */ + /** Returns boolean indicating whether the given script is running on this server */ isRunning(fn: string): boolean { for (const runningScriptObj of this.runningScripts) { if (runningScriptObj.filename === fn) { diff --git a/src/Server/Server.ts b/src/Server/Server.ts index 427b879e3..976163478 100644 --- a/src/Server/Server.ts +++ b/src/Server/Server.ts @@ -86,9 +86,7 @@ export class Server extends BaseServer { this.numOpenPortsRequired = params.numOpenPortsRequired != null ? params.numOpenPortsRequired : 5; } - /** - * Ensures that the server's difficulty (server security) doesn't get too high - */ + /** Ensures that the server's difficulty (server security) doesn't get too high */ capDifficulty(): void { if (this.hackDifficulty < this.minDifficulty) { this.hackDifficulty = this.minDifficulty; @@ -134,25 +132,19 @@ export class Server extends BaseServer { this.moneyMax *= n; } - /** - * Strengthens a server's security level (difficulty) by the specified amount - */ + /** Strengthens a server's security level (difficulty) by the specified amount */ fortify(amt: number): void { this.hackDifficulty += amt; this.capDifficulty(); } - /** - * Lowers the server's security level (difficulty) by the specified amount) - */ + /** Lowers the server's security level (difficulty) by the specified amount) */ weaken(amt: number): void { this.hackDifficulty -= amt * BitNodeMultipliers.ServerWeakenRate; this.capDifficulty(); } - /** - * Serialize the current object to a JSON save state - */ + /** Serialize the current object to a JSON save state */ toJSON(): IReviverValue { return Generic_toJSON("Server", this); } diff --git a/src/Server/data/servers.ts b/src/Server/data/servers.ts index 4c836e011..a90079f64 100644 --- a/src/Server/data/servers.ts +++ b/src/Server/data/servers.ts @@ -12,19 +12,13 @@ import { SpecialServers } from "./SpecialServers"; * These values will be adjusted based on Bitnode multipliers when the Server objects are built out. */ interface IServerMetadata { - /** - * When populated, the base security level of the server. - */ + /** When populated, the base security level of the server. */ hackDifficulty?: number | IMinMaxRange; - /** - * The DNS name of the server. - */ + /** The DNS name of the server. */ hostname: string; - /** - * When populated, the files will be added to the server when created. - */ + /** When populated, the files will be added to the server when created. */ literature?: string[]; /** @@ -33,9 +27,7 @@ interface IServerMetadata { */ maxRamExponent?: number | IMinMaxRange; - /** - * How much money the server starts out with. - */ + /** How much money the server starts out with. */ moneyAvailable: number | IMinMaxRange; /** @@ -45,35 +37,23 @@ interface IServerMetadata { */ networkLayer?: number | IMinMaxRange; - /** - * The number of ports that must be opened before the player can execute NUKE. - */ + /** The number of ports that must be opened before the player can execute NUKE. */ numOpenPortsRequired: number; - /** - * The organization that the server belongs to. - */ + /** The organization that the server belongs to. */ organizationName: string; - /** - * The minimum hacking level before the player can run NUKE. - */ + /** The minimum hacking level before the player can run NUKE. */ requiredHackingSkill: number | IMinMaxRange; - /** - * The growth factor for the server. - */ + /** The growth factor for the server. */ serverGrowth?: number | IMinMaxRange; - /** - * A "unique" server that has special implications when the player manually hacks it. - */ + /** A "unique" server that has special implications when the player manually hacks it. */ specialName?: string; } -/** - * The metadata for building up the servers on the network. - */ +/** The metadata for building up the servers on the network. */ export const serverMetadata: IServerMetadata[] = [ { hackDifficulty: 99, diff --git a/src/Settings/SettingEnums.ts b/src/Settings/SettingEnums.ts index 3980af98f..4a12fc9b4 100644 --- a/src/Settings/SettingEnums.ts +++ b/src/Settings/SettingEnums.ts @@ -1,8 +1,4 @@ -// Enums that defined allowed values for setting configuration - -/** - * Allowed values for the 'OwnedAugmentationsOrder' setting - */ +/** Allowed values for the 'OwnedAugmentationsOrder' setting */ export enum PurchaseAugmentationsOrderSetting { Cost, Default, @@ -10,9 +6,7 @@ export enum PurchaseAugmentationsOrderSetting { Purchasable, } -/** - * Allowed values for the 'OwnedAugmentationsOrder' setting - */ +/** Allowed values for the 'OwnedAugmentationsOrder' setting */ export enum OwnedAugmentationsOrderSetting { Alphabetically, AcquirementTime, diff --git a/src/StockMarket/BuyingAndSelling.tsx b/src/StockMarket/BuyingAndSelling.tsx index c3dc2739b..95d1cf571 100644 --- a/src/StockMarket/BuyingAndSelling.tsx +++ b/src/StockMarket/BuyingAndSelling.tsx @@ -23,9 +23,7 @@ import * as React from "react"; import { NetscriptContext } from "../Netscript/APIWrapper"; import { helpers } from "../Netscript/NetscriptHelpers"; -/** - * Each function takes an optional config object as its last argument - */ +/** Each function takes an optional config object as its last argument */ interface IOptions { rerenderFn?: () => void; suppressDialog?: boolean; diff --git a/src/StockMarket/Order.ts b/src/StockMarket/Order.ts index d37092116..f8fb7399f 100644 --- a/src/StockMarket/Order.ts +++ b/src/StockMarket/Order.ts @@ -43,16 +43,12 @@ export class Order { this.pos = pos; } - /** - * Serialize the Order to a JSON save state. - */ + /** Serialize the Order to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("Order", this); } - /** - * Initializes a Order from a JSON save state - */ + /** Initializes a Order from a JSON save state */ static fromJSON(value: IReviverValue): Order { return Generic_fromJSON(Order, value.data); } diff --git a/src/StockMarket/Stock.ts b/src/StockMarket/Stock.ts index 012da4eda..5d6bb200f 100644 --- a/src/StockMarket/Stock.ts +++ b/src/StockMarket/Stock.ts @@ -51,38 +51,24 @@ function toNumber(n: number | IMinMaxRange): number { return value; } -/** - * Represents the valuation of a company in the World Stock Exchange. - */ +/** Represents the valuation of a company in the World Stock Exchange. */ export class Stock { - /** - * Bear or bull (more likely to go up or down, based on otlkMag) - */ + /** Bear or bull (more likely to go up or down, based on otlkMag) */ b: boolean; - /** - * Maximum price of a stock (per share) - */ + /** Maximum price of a stock (per share) */ readonly cap: number; - /** - * Stocks previous share price - */ + /** Stocks previous share price */ lastPrice: number; - /** - * Maximum number of shares that player can own (both long and short combined) - */ + /** Maximum number of shares that player can own (both long and short combined) */ readonly maxShares: number; - /** - * Maximum volatility - */ + /** Maximum volatility */ readonly mv: number; - /** - * Name of the company that the stock is for - */ + /** Name of the company that the stock is for */ readonly name: string; /** @@ -97,34 +83,22 @@ export class Stock { */ otlkMagForecast: number; - /** - * Average price of stocks that the player owns in the LONG position - */ + /** Average price of stocks that the player owns in the LONG position */ playerAvgPx: number; - /** - * Average price of stocks that the player owns in the SHORT position - */ + /** Average price of stocks that the player owns in the SHORT position */ playerAvgShortPx: number; - /** - * Number of shares the player owns in the LONG position - */ + /** Number of shares the player owns in the LONG position */ playerShares: number; - /** - * Number of shares the player owns in the SHORT position - */ + /** Number of shares the player owns in the SHORT position */ playerShortShares: number; - /** - * Stock's share price - */ + /** Stock's share price */ price: number; - /** - * How many shares need to be transacted in order to trigger a price movement - */ + /** How many shares need to be transacted in order to trigger a price movement */ readonly shareTxForMovement: number; /** @@ -139,9 +113,7 @@ export class Stock { */ readonly spreadPerc: number; - /** - * The stock's ticker symbol - */ + /** The stock's ticker symbol */ readonly symbol: string; /** @@ -178,9 +150,7 @@ export class Stock { this.maxShares = Math.round((this.totalShares * outstandingSharePercentage) / 1e5) * 1e5; } - /** - * Safely set the stock's second-order forecast to a new value - */ + /** Safely set the stock's second-order forecast to a new value */ changeForecastForecast(newff: number): void { this.otlkMagForecast = newff; if (this.otlkMagForecast > 100) { @@ -190,9 +160,7 @@ export class Stock { } } - /** - * Set the stock to a new price. Also updates the stock's previous price tracker - */ + /** Set the stock to a new price. Also updates the stock's previous price tracker */ changePrice(newPrice: number): void { this.lastPrice = this.price; this.price = newPrice; @@ -249,30 +217,22 @@ export class Stock { this.otlkMagForecast = 50 + -1 * diff; } - /** - * Returns the stock's absolute forecast, which is a number between 0-100 - */ + /** Returns the stock's absolute forecast, which is a number between 0-100 */ getAbsoluteForecast(): number { return this.b ? 50 + this.otlkMag : 50 - this.otlkMag; } - /** - * Return the price at which YOUR stock is bought (market ask price). Accounts for spread - */ + /** Return the price at which YOUR stock is bought (market ask price). Accounts for spread */ getAskPrice(): number { return this.price * (1 + this.spreadPerc / 100); } - /** - * Return the price at which YOUR stock is sold (market bid price). Accounts for spread - */ + /** Return the price at which YOUR stock is sold (market bid price). Accounts for spread */ getBidPrice(): number { return this.price * (1 - this.spreadPerc / 100); } - /** - * Returns the chance (0-1 decimal) that a stock has of having its forecast increase - */ + /** Returns the chance (0-1 decimal) that a stock has of having its forecast increase */ getForecastIncreaseChance(): number { const diff = this.otlkMagForecast - this.getAbsoluteForecast(); @@ -305,16 +265,12 @@ export class Stock { } } - /** - * Serialize the Stock to a JSON save state. - */ + /** Serialize the Stock to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("Stock", this); } - /** - * Initializes a Stock from a JSON save state - */ + /** Initializes a Stock from a JSON save state */ static fromJSON(value: IReviverValue): Stock { return Generic_fromJSON(Stock, value.data); } diff --git a/src/StockMarket/StockMarketHelpers.ts b/src/StockMarket/StockMarketHelpers.ts index 3a6e08a21..72bd4dbcb 100644 --- a/src/StockMarket/StockMarketHelpers.ts +++ b/src/StockMarket/StockMarketHelpers.ts @@ -1,6 +1,3 @@ -/** - * Stock Market Helper Functions - */ import { Stock } from "./Stock"; import { PositionTypes } from "./data/PositionTypes"; import { CONSTANTS } from "../Constants"; diff --git a/src/StockMarket/ui/StockMarketRoot.tsx b/src/StockMarket/ui/StockMarketRoot.tsx index a77e213ac..8b5dae9c8 100644 --- a/src/StockMarket/ui/StockMarketRoot.tsx +++ b/src/StockMarket/ui/StockMarketRoot.tsx @@ -1,6 +1,3 @@ -/** - * Root React component for the Stock Market UI - */ import React, { useState, useEffect } from "react"; import { InfoAndPurchases } from "./InfoAndPurchases"; @@ -14,6 +11,7 @@ type IProps = { stockMarket: IStockMarket; }; +/** Root React component for the Stock Market UI */ export function StockMarketRoot(props: IProps): React.ReactElement { const setRerender = useState(false)[1]; function rerender(): void { diff --git a/src/StockMarket/ui/StockTicker.tsx b/src/StockMarket/ui/StockTicker.tsx index 8f3abc596..fa1c456f8 100644 --- a/src/StockMarket/ui/StockTicker.tsx +++ b/src/StockMarket/ui/StockTicker.tsx @@ -1,6 +1,3 @@ -/** - * React Component for a single stock ticker in the Stock Market UI - */ import React, { useState } from "react"; import { StockTickerHeaderText } from "./StockTickerHeaderText"; @@ -46,6 +43,7 @@ type IProps = { stock: Stock; }; +/** React Component for a single stock ticker in the Stock Market UI */ export function StockTicker(props: IProps): React.ReactElement { const [orderType, setOrderType] = useState(SelectorOrderType.Market); const [position, setPosition] = useState(PositionTypes.Long); diff --git a/src/StockMarket/ui/StockTickerOrder.tsx b/src/StockMarket/ui/StockTickerOrder.tsx index b049a3280..ec2b13378 100644 --- a/src/StockMarket/ui/StockTickerOrder.tsx +++ b/src/StockMarket/ui/StockTickerOrder.tsx @@ -1,6 +1,3 @@ -/** - * React component for displaying a single order in a stock's order book - */ import * as React from "react"; import { Order } from "../Order"; @@ -17,6 +14,7 @@ type IProps = { order: Order; }; +/** React component for displaying a single order in a stock's order book */ export function StockTickerOrder(props: IProps): React.ReactElement { function handleCancelOrderClick(): void { cancelOrder({ order: props.order }); diff --git a/src/Terminal/DirectoryHelpers.ts b/src/Terminal/DirectoryHelpers.ts index 067b80949..85659aa62 100644 --- a/src/Terminal/DirectoryHelpers.ts +++ b/src/Terminal/DirectoryHelpers.ts @@ -8,9 +8,7 @@ * found in ./DirectoryServerHelpers.ts */ -/** - * Removes leading forward slash ("/") from a string. - */ +/** Removes leading forward slash ("/") from a string. */ export function removeLeadingSlash(s: string): string { if (s.startsWith("/")) { return s.slice(1); @@ -210,9 +208,7 @@ export function getFileName(path: string): string { return t_path.slice(lastSlash + 1); } -/** - * Checks if a file path refers to a file in the root directory. - */ +/** Checks if a file path refers to a file in the root directory. */ export function isInRootDirectory(path: string): boolean { if (!isValidFilePath(path)) { return false; diff --git a/src/Terminal/DirectoryServerHelpers.ts b/src/Terminal/DirectoryServerHelpers.ts index 8dccbf6e2..9e4b01db3 100644 --- a/src/Terminal/DirectoryServerHelpers.ts +++ b/src/Terminal/DirectoryServerHelpers.ts @@ -52,9 +52,7 @@ export function getSubdirectories(serv: BaseServer, dir: string): string[] { return res; } -/** - * Returns true, if the server's directory itself or one of its subdirectory contains files. - */ +/** Returns true, if the server's directory itself or one of its subdirectory contains files. */ export function containsFiles(server: BaseServer, dir: string): boolean { const dirWithTrailingSlash = dir + (dir.slice(-1) === "/" ? "" : "/"); diff --git a/src/TextFile.ts b/src/TextFile.ts index 948b4f1d1..a87de56f3 100644 --- a/src/TextFile.ts +++ b/src/TextFile.ts @@ -3,30 +3,21 @@ import { BaseServer } from "./Server/BaseServer"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "./utils/JSONReviver"; import { removeLeadingSlash, isInRootDirectory } from "./Terminal/DirectoryHelpers"; -/** - * Represents a plain text file that is typically stored on a server. - */ +/** Represents a plain text file that is typically stored on a server. */ export class TextFile { - /** - * The full file name. - */ + /** The full file name. */ fn: string; - /** - * The content of the file. - */ + /** The content of the file. */ text: string; - /** - * The full file name. - */ + //TODO: Why are we using getter/setter for fn as filename? + /** The full file name. */ get filename(): string { return this.fn; } - /** - * The full file name. - */ + /** The full file name. */ set filename(value: string) { this.fn = value; } @@ -36,16 +27,12 @@ export class TextFile { this.text = txt; } - /** - * Concatenates the raw values to the end of current content. - */ + /** Concatenates the raw values to the end of current content. */ append(txt: string): void { this.text += txt; } - /** - * Serves the file to the user as a downloadable resource through the browser. - */ + /** Serves the file to the user as a downloadable resource through the browser. */ download(): void { const file: Blob = new Blob([this.text], { type: "text/plain" }); const a: HTMLAnchorElement = document.createElement("a"); @@ -60,37 +47,27 @@ export class TextFile { }, 0); } - /** - * Retrieve the content of the file. - */ + /** Retrieve the content of the file. */ read(): string { return this.text; } - /** - * Shows the content to the user via the game's dialog box. - */ + /** Shows the content to the user via the game's dialog box. */ show(): void { dialogBoxCreate(`${this.fn}

${this.text}`); } - /** - * Serialize the current file to a JSON save state. - */ + /** Serialize the current file to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("TextFile", this); } - /** - * Replaces the current content with the text provided. - */ + /** Replaces the current content with the text provided. */ write(txt: string): void { this.text = txt; } - /** - * Initiatizes a TextFile from a JSON save state. - */ + /** Initiatizes a TextFile from a JSON save state. */ static fromJSON(value: IReviverValue): TextFile { return Generic_fromJSON(TextFile, value.data); } diff --git a/src/Themes/ui/ThemeBrowser.tsx b/src/Themes/ui/ThemeBrowser.tsx index d7d9275bb..e8cee63c7 100644 --- a/src/Themes/ui/ThemeBrowser.tsx +++ b/src/Themes/ui/ThemeBrowser.tsx @@ -10,7 +10,7 @@ import { StyleEditorButton } from "./StyleEditorButton"; import { ThemeEntry } from "./ThemeEntry"; import { ThemeCollaborate } from "./ThemeCollaborate"; import { Modal } from "../../ui/React/Modal"; -import { SnackbarEvents } from "../../ui/React/Snackbar"; +import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar"; // Everything dies when the theme gets reloaded, so we'll keep the current scroll to not jump around. let previousScrollY = 0; @@ -49,7 +49,7 @@ export function ThemeBrowser(): React.ReactElement { UNDO , - "info", + ToastVariant.INFO, 30000, ); } diff --git a/src/Work/ClassWork.tsx b/src/Work/ClassWork.tsx index 3690978d6..b41d2f677 100644 --- a/src/Work/ClassWork.tsx +++ b/src/Work/ClassWork.tsx @@ -188,16 +188,12 @@ export class ClassWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("ClassWork", this); } - /** - * Initiatizes a ClassWork object from a JSON save state. - */ + /** Initiatizes a ClassWork object from a JSON save state. */ static fromJSON(value: IReviverValue): ClassWork { return Generic_fromJSON(ClassWork, value.data); } diff --git a/src/Work/CompanyWork.tsx b/src/Work/CompanyWork.tsx index 85110951d..ae9271bd6 100644 --- a/src/Work/CompanyWork.tsx +++ b/src/Work/CompanyWork.tsx @@ -70,16 +70,12 @@ export class CompanyWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("CompanyWork", this); } - /** - * Initiatizes a CompanyWork object from a JSON save state. - */ + /** Initiatizes a CompanyWork object from a JSON save state. */ static fromJSON(value: IReviverValue): CompanyWork { return Generic_fromJSON(CompanyWork, value.data); } diff --git a/src/Work/CreateProgramWork.ts b/src/Work/CreateProgramWork.ts index 1a8e97070..30180f1d9 100644 --- a/src/Work/CreateProgramWork.ts +++ b/src/Work/CreateProgramWork.ts @@ -107,16 +107,12 @@ export class CreateProgramWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("CreateProgramWork", this); } - /** - * Initiatizes a CreateProgramWork object from a JSON save state. - */ + /** Initiatizes a CreateProgramWork object from a JSON save state. */ static fromJSON(value: IReviverValue): CreateProgramWork { return Generic_fromJSON(CreateProgramWork, value.data); } diff --git a/src/Work/CrimeWork.ts b/src/Work/CrimeWork.ts index 2ea4a0cb2..dd7b20f80 100644 --- a/src/Work/CrimeWork.ts +++ b/src/Work/CrimeWork.ts @@ -136,16 +136,12 @@ export class CrimeWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("CrimeWork", this); } - /** - * Initiatizes a CrimeWork object from a JSON save state. - */ + /** Initiatizes a CrimeWork object from a JSON save state. */ static fromJSON(value: IReviverValue): CrimeWork { return Generic_fromJSON(CrimeWork, value.data); } diff --git a/src/Work/FactionWork.tsx b/src/Work/FactionWork.tsx index a8464ce86..8a365e8c5 100644 --- a/src/Work/FactionWork.tsx +++ b/src/Work/FactionWork.tsx @@ -85,16 +85,12 @@ export class FactionWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("FactionWork", this); } - /** - * Initiatizes a FactionWork object from a JSON save state. - */ + /** Initiatizes a FactionWork object from a JSON save state. */ static fromJSON(value: IReviverValue): FactionWork { return Generic_fromJSON(FactionWork, value.data); } diff --git a/src/Work/GraftingWork.tsx b/src/Work/GraftingWork.tsx index 6b8c75dc0..498e88ee0 100644 --- a/src/Work/GraftingWork.tsx +++ b/src/Work/GraftingWork.tsx @@ -91,16 +91,12 @@ export class GraftingWork extends Work { }; } - /** - * Serialize the current object to a JSON save state. - */ + /** Serialize the current object to a JSON save state. */ toJSON(): IReviverValue { return Generic_toJSON("GraftingWork", this); } - /** - * Initiatizes a GraftingWork object from a JSON save state. - */ + /** Initiatizes a GraftingWork object from a JSON save state. */ static fromJSON(value: IReviverValue): GraftingWork { return Generic_fromJSON(GraftingWork, value.data); } diff --git a/src/engine.tsx b/src/engine.tsx index 81380c1a6..880e66626 100644 --- a/src/engine.tsx +++ b/src/engine.tsx @@ -1,6 +1,3 @@ -/** - * Game engine. Handles the main game loop. - */ import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions"; import { initAugmentations } from "./Augmentation/AugmentationHelpers"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; @@ -46,8 +43,9 @@ import { calculateAchievements } from "./Achievements/Achievements"; import React from "react"; import { setupUncaughtPromiseHandler } from "./UncaughtPromiseHandler"; import { Button, Typography } from "@mui/material"; -import { SnackbarEvents } from "./ui/React/Snackbar"; +import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; +/** Game engine. Handles the main game loop. */ const Engine: { _lastUpdate: number; updateGame: (numCycles?: number) => void; @@ -403,9 +401,7 @@ const Engine: { }, }; -/** - * Shows a toast warning that lets the player know that auto-saves are disabled, with an button to re-enable them. - */ +/** Shows a toast warning that lets the player know that auto-saves are disabled, with an button to re-enable them. */ function warnAutosaveDisabled(): void { // If the player has suppressed those warnings let's just exit right away. if (Settings.SuppressAutosaveDisabledWarnings) return; @@ -431,7 +427,7 @@ function warnAutosaveDisabled(): void { ); - SnackbarEvents.emit(warningToast, "warning", 5000); + SnackbarEvents.emit(warningToast, ToastVariant.WARNING, 5000); } export { Engine }; diff --git a/src/types.ts b/src/types.ts index 9a5388765..054accfc4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,9 +1,6 @@ /** Construct a type using the values from an object. Requires object to be defined "as const" */ export type ValuesFrom = T[keyof T]; -/** Only allowed to be true if the types are equal. */ -export type TypeEquality = [T1] extends [T2] ? ([T2] extends [T1] ? true : false) : false; - /** * Status object for functions that return a boolean indicating success/failure * and an optional message @@ -19,18 +16,12 @@ export interface IReturnStatus { * It is up to the implementor to ensure max > min. */ export interface IMinMaxRange { - /** - * Value by which the bounds are to be divided for the final range - */ + /** Value by which the bounds are to be divided for the final range */ divisor?: number; - /** - * The maximum bound of the range. - */ + /** The maximum bound of the range. */ max: number; - /** - * The minimum bound of the range. - */ + /** The minimum bound of the range. */ min: number; } diff --git a/src/ui/React/Snackbar.tsx b/src/ui/React/Snackbar.tsx index c851129bb..0225418f3 100644 --- a/src/ui/React/Snackbar.tsx +++ b/src/ui/React/Snackbar.tsx @@ -10,7 +10,12 @@ interface IProps { children: React.ReactNode | React.ReactNode[]; } -export type ToastVariant = AlertColor; +export enum ToastVariant{ + SUCCESS = "success", + WARNING = "warning", + ERROR = "error", + INFO = "info", +}; const useStyles = makeStyles(() => ({ snackbar: { diff --git a/src/ui/Router.ts b/src/ui/Router.ts index 44422d863..9a4536746 100644 --- a/src/ui/Router.ts +++ b/src/ui/Router.ts @@ -45,9 +45,7 @@ export interface ScriptEditorRouteOptions { vim: boolean; } -/** - * This class keeps track of player navigation/routing within the game. - */ +/** The router keeps track of player navigation/routing within the game. */ export interface IRouter { // toCinematicText(): void; // toInfiltration(): void; diff --git a/src/utils/EventEmitter.ts b/src/utils/EventEmitter.ts index 94cc70e13..425118c98 100644 --- a/src/utils/EventEmitter.ts +++ b/src/utils/EventEmitter.ts @@ -1,6 +1,3 @@ -/** - * Generic Event Emitter class following a subscribe/publish paradigm. - */ function uuidv4(): string { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { const r = (Math.random() * 16) | 0, @@ -9,6 +6,7 @@ function uuidv4(): string { }); } +/** Generic Event Emitter class following a subscribe/publish paradigm. */ export class EventEmitter { subscribers: { [key: string]: (...args: [...T]) => void | undefined } = {}; diff --git a/src/utils/helpers/createProgressBarText.ts b/src/utils/helpers/createProgressBarText.ts index 6da10f0ca..6bd5be072 100644 --- a/src/utils/helpers/createProgressBarText.ts +++ b/src/utils/helpers/createProgressBarText.ts @@ -1,21 +1,13 @@ -/** - * Represents the possible configuration values that can be provided when creating the progress bar text. - */ +/** Represents the possible configuration values that can be provided when creating the progress bar text. */ interface IProgressBarConfiguration { - /** - * Current progress, taken as a decimal (i.e. '0.6' to represent '60%') - */ + /** Current progress, taken as a decimal (i.e. '0.6' to represent '60%') */ progress?: number; - /** - * Total number of ticks in progress bar. Preferably a factor of 100. - */ + /** Total number of ticks in progress bar. Preferably a factor of 100. */ totalTicks?: number; } -/** - * Represents concrete configuration values when creating the progress bar text. - */ +/** Represents concrete configuration values when creating the progress bar text. */ interface IProgressBarConfigurationMaterialized extends IProgressBarConfiguration { progress: number; totalTicks: number; diff --git a/src/utils/helpers/getTimestamp.ts b/src/utils/helpers/getTimestamp.ts index d4cc96979..c1f989b33 100644 --- a/src/utils/helpers/getTimestamp.ts +++ b/src/utils/helpers/getTimestamp.ts @@ -1,6 +1,4 @@ -/** - * Returns a MM/DD HH:MM timestamp for the current time - */ +/** Returns a MM/DD HH:MM timestamp for the current time */ export function getTimestamp(): string { const d: Date = new Date(); // A negative slice value takes from the end of the string rather than the beginning. diff --git a/src/utils/helpers/keyCodes.ts b/src/utils/helpers/keyCodes.ts index 8e52d13bd..a976ca615 100644 --- a/src/utils/helpers/keyCodes.ts +++ b/src/utils/helpers/keyCodes.ts @@ -1,6 +1,4 @@ -/** - * Keyboard key codes as returned by event.key - */ +/** Keyboard key codes as returned by event.key */ export enum KEY { //SHIFT: 16, // Check by `&& event.shiftKey` //CTRL: 17, // Check by `&& event.ctrlKey` @@ -72,9 +70,7 @@ export enum KEY { Z = "z", } -/** - * Keyboard key codes as returned by event.code - */ +/** Keyboard key codes as returned by event.code */ export enum KEYCODE { //SHIFT: 16, // Check by `&& event.shiftKey` //CTRL: 17, // Check by `&& event.ctrlKey` From 361466b7fa2c39507ad69b912a8b325fa1dec2e5 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 4 Oct 2022 07:59:50 -0400 Subject: [PATCH 3/8] unasync trywriteport --- doc/source/netscript/netscriptjs.rst | 8 ++------ src/NetscriptFunctions.ts | 4 ++-- src/ScriptEditor/NetscriptDefinitions.d.ts | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/doc/source/netscript/netscriptjs.rst b/doc/source/netscript/netscriptjs.rst index 84365306b..70d5fc12c 100644 --- a/doc/source/netscript/netscriptjs.rst +++ b/doc/source/netscript/netscriptjs.rst @@ -51,11 +51,9 @@ Here is a summary of all rules you need to follow when writing Netscript JS code * grow * weaken * sleep + * asleep * prompt * wget - * scp - * write - * writePort * Any function that contains :code:`await` must be declared as :code:`async` @@ -147,9 +145,7 @@ You may have noticed that every new ns2 file will contains the following comment .. code-block:: javascript - /** - * @param {NS} ns - **/ + /** @param {NS} ns */ This comment is used to help the text editor autocomplete functions in the Netscript API. You can enable it by pressing ctrl+space after `ns.` diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 201c4a154..816abad79 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -1518,7 +1518,7 @@ const base: InternalAPI = { }, tryWritePort: (ctx: NetscriptContext) => - (_port: unknown, data: unknown = ""): Promise => { + (_port: unknown, data: unknown = ""): boolean => { const port = helpers.number(ctx, "port", _port); if (typeof data !== "string" && typeof data !== "number") { throw helpers.makeRuntimeErrorMsg( @@ -1527,7 +1527,7 @@ const base: InternalAPI = { ); } const iport = helpers.getValidPort(ctx, port); - return Promise.resolve(iport.tryWrite(data)); + return iport.tryWrite(data); }, readPort: (ctx: NetscriptContext) => diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index e09ba697b..da7bf0f45 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -5969,7 +5969,7 @@ export interface NS { * @param data - Data to write. * @returns True if the data is successfully written to the port, and false otherwise. */ - tryWritePort(port: number, data: string | number): Promise; + tryWritePort(port: number, data: string | number): boolean; /** * Read content of a file. From e71e5988cbcd1063d535a76ad2be476ff48ef439 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 4 Oct 2022 11:56:36 -0400 Subject: [PATCH 4/8] unify static and dynamic ram tests --- .../Netscript/DynamicRamCalculation.test.ts | 1195 ----------------- test/jest/Netscript/RamCalculation.test.ts | 217 +++ .../Netscript/StaticRamCalculation.test.ts | 1164 ---------------- 3 files changed, 217 insertions(+), 2359 deletions(-) delete mode 100644 test/jest/Netscript/DynamicRamCalculation.test.ts create mode 100644 test/jest/Netscript/RamCalculation.test.ts delete mode 100644 test/jest/Netscript/StaticRamCalculation.test.ts diff --git a/test/jest/Netscript/DynamicRamCalculation.test.ts b/test/jest/Netscript/DynamicRamCalculation.test.ts deleted file mode 100644 index 8e4920022..000000000 --- a/test/jest/Netscript/DynamicRamCalculation.test.ts +++ /dev/null @@ -1,1195 +0,0 @@ -import { NetscriptFunctions } from "../../../src/NetscriptFunctions"; -import { getRamCost, RamCostConstants } from "../../../src/Netscript/RamCostGenerator"; -import { Environment } from "../../../src/Netscript/Environment"; -import { RunningScript } from "../../../src/Script/RunningScript"; -import { Script } from "../../../src/Script/Script"; -import { WorkerScript } from "../../../src/Netscript/WorkerScript"; - -describe("Netscript Dynamic RAM Calculation/Generation Tests", function () { - const ScriptBaseCost = RamCostConstants.ScriptBaseRamCost; - // Creates a mock RunningScript object - /** - * - * @param {string} code - * @returns - */ - function createRunningScript(code: string) { - const script = new Script(); - script.code = code; - script.updateRamUsage([]); - - const runningScript = new RunningScript(script); - - return runningScript; - } - - // Tests numeric equality, allowing for floating point imprecision - /** - * - * @param {number} val - * @param {number} expected - */ - function testEquality(val: number, expected: number) { - expect(val).toBeGreaterThanOrEqual(expected - 100 * Number.EPSILON); - expect(val).toBeLessThanOrEqual(expected + 100 * Number.EPSILON); - } - - // Runs a Netscript function and properly catches it if it returns promise - - /** - * - * @param {(...args: unknown[]) => unknown} fn - * @param {unknown[]} args - */ - function runPotentiallyAsyncFunction( - fn: (...args: (string | number | boolean)[]) => unknown, - ...args: (string | number | boolean)[] - ) { - const res = fn(...args); - if (res instanceof Promise) { - res.catch(() => undefined); - } - } - - /** - * Tests that: - * 1. A function has non-zero RAM cost - * 2. Running the function properly updates the MockWorkerScript's dynamic RAM calculation - * 3. Running multiple calls of the function does not result in additional RAM cost - * @param {string[]} fnDesc - describes the name of the function being tested, - * including the namespace(s). e.g. ["gang", "getMemberNames"] - */ - async function testNonzeroDynamicRamCost(fnDesc: string[], ...args: (string | number | boolean)[]) { - if (!Array.isArray(fnDesc)) { - throw new Error("Non-array passed to testNonzeroDynamicRamCost()"); - } - const expected = getRamCost(...fnDesc); - expect(expected).toBeGreaterThan(0); - - const code = `${fnDesc.join(".")}();`; - - const runningScript = createRunningScript(code); - - // We don't need a real WorkerScript - const workerScript = { - args: args, - code: code, - delay: null, - dynamicLoadedFns: {}, - dynamicRamUsage: RamCostConstants.ScriptBaseRamCost, - env: new Environment(), - ramUsage: runningScript.ramUsage, - scriptRef: runningScript, - }; - workerScript.env.vars = NetscriptFunctions(workerScript as WorkerScript); - - // Run the function through the workerscript's args - const scope = workerScript.env.vars; - const curr = fnDesc.reduce((prev, curr) => { - try { - return prev[curr]; - } catch { - throw new Error(`Invalid function: [${fnDesc}]`); - } - }, scope as any); - - if (typeof curr === "function") { - // We use a try/catch because the function will probably fail since the game isn't - // actually initialized. Call the fn multiple times to test that repeated calls - // do not incur extra RAM costs. - try { - runPotentiallyAsyncFunction(curr, ...args); - runPotentiallyAsyncFunction(curr, ...args); - runPotentiallyAsyncFunction(curr, ...args); - } catch (e) {} - } else { - throw new Error(`Invalid function specified: [${fnDesc.toString()}]`); - } - - const fnName = fnDesc[fnDesc.length - 1]; - testEquality(workerScript.dynamicRamUsage - ScriptBaseCost, expected); - testEquality(workerScript.dynamicRamUsage, runningScript.ramUsage); - expect(workerScript.dynamicLoadedFns).toHaveProperty(fnName); - } - - /** - * Tests that: - * 1. A function has zero RAM cost - * 2. Running the function does NOT update the MockWorkerScript's dynamic RAM calculation - * 3. Running multiple calls of the function does not result in dynamic RAM calculation - * @param {string[]} fnDesc - describes the name of the function being tested, - * including the namespace(s). e.g. ["gang", "getMemberNames"] - */ - async function testZeroDynamicRamCost(fnDesc: string[], skipRun = false) { - if (!Array.isArray(fnDesc)) { - throw new Error("Non-array passed to testZeroDynamicRamCost()"); - } - const expected = getRamCost(...fnDesc); - expect(expected).toEqual(0); - if (skipRun) return; - - const code = `${fnDesc.join(".")}();`; - - const runningScript = createRunningScript(code); - - // We don't need a real WorkerScript - const workerScript = { - args: [], - code: code, - dynamicLoadedFns: {}, - dynamicRamUsage: RamCostConstants.ScriptBaseRamCost, - env: new Environment(), - ramUsage: runningScript.ramUsage, - scriptRef: runningScript, - }; - workerScript.env.vars = NetscriptFunctions(workerScript as unknown as WorkerScript); - - // Run the function through the workerscript's args - const scope = workerScript.env.vars; - const curr = fnDesc.reduce((prev, curr) => { - try { - return prev[curr]; - } catch { - throw new Error(`Invalid function: [${fnDesc}]`); - } - }, scope as any); - - if (typeof curr === "function") { - // We use a try/catch because the function will probably fail since the game isn't - // actually initialized. Call the fn multiple times to test that repeated calls - // do not incur extra RAM costs. - try { - runPotentiallyAsyncFunction(curr); - runPotentiallyAsyncFunction(curr); - runPotentiallyAsyncFunction(curr); - } catch (e) {} - } else { - throw new Error(`Invalid function specified: [${fnDesc}]`); - } - - testEquality(workerScript.dynamicRamUsage, ScriptBaseCost); - testEquality(workerScript.dynamicRamUsage, runningScript.ramUsage); - } - - describe("Basic Functions", function () { - it("hack()", async function () { - const f = ["hack"]; - await testNonzeroDynamicRamCost(f); - }); - - it("grow()", async function () { - const f = ["grow"]; - await testNonzeroDynamicRamCost(f); - }); - - it("weaken()", async function () { - const f = ["weaken"]; - await testNonzeroDynamicRamCost(f); - }); - - it("hackAnalyzeThreads()", async function () { - const f = ["hackAnalyzeThreads"]; - await testNonzeroDynamicRamCost(f); - }); - - it("hackAnalyze()", async function () { - const f = ["hackAnalyze"]; - await testNonzeroDynamicRamCost(f); - }); - - it("hackAnalyzeChance()", async function () { - const f = ["hackAnalyzeChance"]; - await testNonzeroDynamicRamCost(f); - }); - - it("growthAnalyze()", async function () { - const f = ["growthAnalyze"]; - await testNonzeroDynamicRamCost(f); - }); - - it("sleep()", async function () { - const f = ["sleep"]; - await testZeroDynamicRamCost(f); - }); - - it("print()", async function () { - const f = ["print"]; - await testZeroDynamicRamCost(f); - }); - - it("tprint()", async function () { - const f = ["tprint"]; - await testZeroDynamicRamCost(f); - }); - - it("clearLog()", async function () { - const f = ["clearLog"]; - await testZeroDynamicRamCost(f); - }); - - it("disableLog()", async function () { - const f = ["disableLog"]; - await testZeroDynamicRamCost(f); - }); - - it("enableLog()", async function () { - const f = ["enableLog"]; - await testZeroDynamicRamCost(f); - }); - - it("isLogEnabled()", async function () { - const f = ["isLogEnabled"]; - await testZeroDynamicRamCost(f); - }); - - it("getScriptLogs()", async function () { - const f = ["getScriptLogs"]; - await testZeroDynamicRamCost(f); - }); - - it("scan()", async function () { - const f = ["scan"]; - await testNonzeroDynamicRamCost(f); - }); - - it("nuke()", async function () { - const f = ["nuke"]; - await testNonzeroDynamicRamCost(f); - }); - - it("brutessh()", async function () { - const f = ["brutessh"]; - await testNonzeroDynamicRamCost(f); - }); - - it("ftpcrack()", async function () { - const f = ["ftpcrack"]; - await testNonzeroDynamicRamCost(f); - }); - - it("relaysmtp()", async function () { - const f = ["relaysmtp"]; - await testNonzeroDynamicRamCost(f); - }); - - it("httpworm()", async function () { - const f = ["httpworm"]; - await testNonzeroDynamicRamCost(f); - }); - - it("sqlinject()", async function () { - const f = ["sqlinject"]; - await testNonzeroDynamicRamCost(f); - }); - - it("run()", async function () { - const f = ["run"]; - await testNonzeroDynamicRamCost(f); - }); - - it("exec()", async function () { - const f = ["exec"]; - jest.spyOn(console, "log").mockImplementation(() => {}); // eslint-disable-line - await testNonzeroDynamicRamCost(f); - }); - - it("spawn()", async function () { - const f = ["spawn"]; - await testNonzeroDynamicRamCost(f); - }); - - it("kill()", async function () { - const f = ["kill"]; - await testNonzeroDynamicRamCost(f); - }); - - it("killall()", async function () { - const f = ["killall"]; - await testNonzeroDynamicRamCost(f); - }); - - it("exit()", async function () { - const f = ["exit"]; - await testZeroDynamicRamCost(f, true); - }); - - it("scp()", async function () { - const f = ["scp"]; - await testNonzeroDynamicRamCost(f); - }); - - it("ls()", async function () { - const f = ["ls"]; - await testNonzeroDynamicRamCost(f); - }); - - it("ps()", async function () { - const f = ["ps"]; - await testNonzeroDynamicRamCost(f); - }); - - it("hasRootAccess()", async function () { - const f = ["hasRootAccess"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getHostname()", async function () { - const f = ["getHostname"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getHackingLevel()", async function () { - const f = ["getHackingLevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getHackingMultipliers()", async function () { - const f = ["getHackingMultipliers"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getHacknetMultipliers()", async function () { - const f = ["getHacknetMultipliers"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getServerMoneyAvailable()", async function () { - const f = ["getServerMoneyAvailable"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getServerMaxMoney()", async function () { - const f = ["getServerMaxMoney"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getServerGrowth()", async function () { - const f = ["getServerGrowth"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getServerSecurityLevel()", async function () { - const f = ["getServerSecurityLevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getServerBaseSecurityLevel()", async function () { - const f = ["getServerBaseSecurityLevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getServerMinSecurityLevel()", async function () { - const f = ["getServerMinSecurityLevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getServerRequiredHackingLevel()", async function () { - const f = ["getServerRequiredHackingLevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getServerNumPortsRequired()", async function () { - const f = ["getServerNumPortsRequired"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getServerRam()", async function () { - const f = ["getServerRam"]; - 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); - }); - - it("fileExists()", async function () { - const f = ["fileExists"]; - await testNonzeroDynamicRamCost(f); - }); - - it("isRunning()", async function () { - const f = ["isRunning"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getPurchasedServerCost()", async function () { - const f = ["getPurchasedServerCost"]; - await testNonzeroDynamicRamCost(f); - }); - - it("purchaseServer()", async function () { - const f = ["purchaseServer"]; - await testNonzeroDynamicRamCost(f, "abc", "64"); - }); - - it("deleteServer()", async function () { - const f = ["deleteServer"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getPurchasedServers()", async function () { - const f = ["getPurchasedServers"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getPurchasedServerLimit()", async function () { - const f = ["getPurchasedServerLimit"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getPurchasedServerMaxRam()", async function () { - const f = ["getPurchasedServerMaxRam"]; - await testNonzeroDynamicRamCost(f); - }); - - it("write()", async function () { - const f = ["write"]; - await testZeroDynamicRamCost(f); - }); - - it("tryWritePort()", async function () { - const f = ["tryWritePort"]; - await testZeroDynamicRamCost(f); - }); - - it("read()", async function () { - const f = ["read"]; - await testZeroDynamicRamCost(f); - }); - - it("peek()", async function () { - const f = ["peek"]; - await testZeroDynamicRamCost(f); - }); - - it("clear()", async function () { - const f = ["clear"]; - await testZeroDynamicRamCost(f); - }); - - it("getPortHandle()", async function () { - const f = ["getPortHandle"]; - await testZeroDynamicRamCost(f); - }); - - it("rm()", async function () { - const f = ["rm"]; - await testNonzeroDynamicRamCost(f); - }); - - it("scriptRunning()", async function () { - const f = ["scriptRunning"]; - await testNonzeroDynamicRamCost(f); - }); - - it("scriptKill()", async function () { - const f = ["scriptKill"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getScriptName()", async function () { - const f = ["getScriptName"]; - await testZeroDynamicRamCost(f); - }); - - it("getScriptRam()", async function () { - const f = ["getScriptRam"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getHackTime()", async function () { - const f = ["getHackTime"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getGrowTime()", async function () { - const f = ["getGrowTime"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getWeakenTime()", async function () { - const f = ["getWeakenTime"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getScriptIncome()", async function () { - const f = ["getScriptIncome"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getScriptExpGain()", async function () { - const f = ["getScriptExpGain"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getRunningScript()", async function () { - const f = ["getRunningScript"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getTimeSinceLastAug()", async function () { - const f = ["getTimeSinceLastAug"]; - await testNonzeroDynamicRamCost(f); - }); - - it("sprintf()", async function () { - const f = ["sprintf"]; - await testZeroDynamicRamCost(f); - }); - - it("vsprintf()", async function () { - const f = ["vsprintf"]; - await testZeroDynamicRamCost(f); - }); - - it("nFormat()", async function () { - const f = ["nFormat"]; - await testZeroDynamicRamCost(f); - }); - - it("prompt()", async function () { - const f = ["prompt"]; - await testZeroDynamicRamCost(f); - }); - - it("wget()", async function () { - const f = ["wget"]; - await testZeroDynamicRamCost(f); - }); - - it("getFavorToDonate()", async function () { - const f = ["getFavorToDonate"]; - await testNonzeroDynamicRamCost(f); - }); - }); - - describe("Advanced Functions", function () { - it("getBitNodeMultipliers()", async function () { - const f = ["getBitNodeMultipliers"]; - await testNonzeroDynamicRamCost(f); - }); - }); - - describe("TIX API", function () { - it("stock.getSymbols()", async function () { - const f = ["stock", "getSymbols"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.getPrice()", async function () { - const f = ["stock", "getPrice"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.getBidPrice()", async function () { - const f = ["stock", "getBidPrice"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.getBidPrice()", async function () { - const f = ["stock", "getBidPrice"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.getPosition()", async function () { - const f = ["stock", "getPosition"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.getMaxShares()", async function () { - const f = ["stock", "getMaxShares"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.buyStock()", async function () { - const f = ["stock", "buyStock"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.sellStock()", async function () { - const f = ["stock", "sellStock"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.sellShort()", async function () { - const f = ["stock", "sellShort"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.placeOrder()", async function () { - const f = ["stock", "placeOrder"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.cancelOrder()", async function () { - const f = ["stock", "cancelOrder"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.getOrders()", async function () { - const f = ["stock", "getOrders"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.getVolatility()", async function () { - const f = ["stock", "getVolatility"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.getForecast()", async function () { - const f = ["stock", "getForecast"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.purchase4SMarketData()", async function () { - const f = ["stock", "purchase4SMarketData"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stock.purchase4SMarketDataTixApi()", async function () { - const f = ["stock", "purchase4SMarketDataTixApi"]; - await testNonzeroDynamicRamCost(f); - }); - }); - - describe("Singularity Functions", function () { - it("universityCourse()", async function () { - const f = ["singularity", "universityCourse"]; - await testNonzeroDynamicRamCost(f); - }); - - it("gymWorkout()", async function () { - const f = ["singularity", "gymWorkout"]; - await testNonzeroDynamicRamCost(f); - }); - - it("travelToCity()", async function () { - const f = ["singularity", "travelToCity"]; - await testNonzeroDynamicRamCost(f); - }); - - it("purchaseTor()", async function () { - const f = ["singularity", "purchaseTor"]; - await testNonzeroDynamicRamCost(f); - }); - - it("purchaseProgram()", async function () { - const f = ["singularity", "purchaseProgram"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getDarkwebProgramCost()", async function () { - const f = ["singularity", "getDarkwebProgramCost"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getDarkwebPrograms()", async function () { - const f = ["singularity", "getDarkwebPrograms"]; - await testNonzeroDynamicRamCost(f); - }); - - it("isBusy()", async function () { - const f = ["singularity", "isBusy"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stopAction()", async function () { - const f = ["singularity", "stopAction"]; - await testNonzeroDynamicRamCost(f); - }); - - it("upgradeHomeRam()", async function () { - const f = ["singularity", "upgradeHomeRam"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getUpgradeHomeRamCost()", async function () { - const f = ["singularity", "getUpgradeHomeRamCost"]; - await testNonzeroDynamicRamCost(f); - }); - - it("workForCompany()", async function () { - const f = ["singularity", "workForCompany"]; - await testNonzeroDynamicRamCost(f); - }); - - it("applyToCompany()", async function () { - const f = ["singularity", "applyToCompany"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getCompanyRep()", async function () { - const f = ["singularity", "getCompanyRep"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getCompanyFavor()", async function () { - const f = ["singularity", "getCompanyFavor"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getCompanyFavorGain()", async function () { - const f = ["singularity", "getCompanyFavorGain"]; - await testNonzeroDynamicRamCost(f); - }); - - it("checkFactionInvitations()", async function () { - const f = ["singularity", "checkFactionInvitations"]; - await testNonzeroDynamicRamCost(f); - }); - - it("joinFaction()", async function () { - const f = ["singularity", "joinFaction"]; - await testNonzeroDynamicRamCost(f); - }); - - it("workForFaction()", async function () { - const f = ["singularity", "workForFaction"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getFactionRep()", async function () { - const f = ["singularity", "getFactionRep"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getFactionFavor()", async function () { - const f = ["singularity", "getFactionFavor"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getFactionFavorGain()", async function () { - const f = ["singularity", "getFactionFavorGain"]; - await testNonzeroDynamicRamCost(f); - }); - - it("donateToFaction()", async function () { - const f = ["singularity", "donateToFaction"]; - await testNonzeroDynamicRamCost(f); - }); - - it("createProgram()", async function () { - const f = ["singularity", "createProgram"]; - await testNonzeroDynamicRamCost(f); - }); - - it("commitCrime()", async function () { - const f = ["singularity", "commitCrime"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getCrimeChance()", async function () { - const f = ["singularity", "getCrimeChance"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getOwnedAugmentations()", async function () { - const f = ["singularity", "getOwnedAugmentations"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getOwnedSourceFiles()", async function () { - const f = ["singularity", "getOwnedSourceFiles"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getAugmentationsFromFaction()", async function () { - const f = ["singularity", "getAugmentationsFromFaction"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getAugmentationCost()", async function () { - const f = ["singularity", "getAugmentationCost"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getAugmentationPrereq()", async function () { - const f = ["singularity", "getAugmentationPrereq"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getAugmentationPrice()", async function () { - const f = ["singularity", "getAugmentationPrice"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getAugmentationRepReq()", async function () { - const f = ["singularity", "getAugmentationRepReq"]; - await testNonzeroDynamicRamCost(f); - }); - - it("purchaseAugmentation()", async function () { - const f = ["singularity", "purchaseAugmentation"]; - await testNonzeroDynamicRamCost(f); - }); - - it("installAugmentations()", async function () { - const f = ["singularity", "installAugmentations"]; - await testNonzeroDynamicRamCost(f); - }); - }); - - describe("Bladeburner API", function () { - it("getContractNames()", async function () { - const f = ["bladeburner", "getContractNames"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getOperationNames()", async function () { - const f = ["bladeburner", "getOperationNames"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getBlackOpNames()", async function () { - const f = ["bladeburner", "getBlackOpNames"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getGeneralActionNames()", async function () { - const f = ["bladeburner", "getGeneralActionNames"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getSkillNames()", async function () { - const f = ["bladeburner", "getSkillNames"]; - await testNonzeroDynamicRamCost(f); - }); - - it("startAction()", async function () { - const f = ["bladeburner", "startAction"]; - await testNonzeroDynamicRamCost(f); - }); - - it("stopBladeburnerAction()", async function () { - const f = ["bladeburner", "stopBladeburnerAction"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getCurrentAction()", async function () { - const f = ["bladeburner", "getCurrentAction"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getActionTime()", async function () { - const f = ["bladeburner", "getActionTime"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getActionEstimatedSuccessChance()", async function () { - const f = ["bladeburner", "getActionEstimatedSuccessChance"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getActionRepGain()", async function () { - const f = ["bladeburner", "getActionRepGain"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getActionCountRemaining()", async function () { - const f = ["bladeburner", "getActionCountRemaining"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getActionMaxLevel()", async function () { - const f = ["bladeburner", "getActionMaxLevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getActionCurrentLevel()", async function () { - const f = ["bladeburner", "getActionCurrentLevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getActionAutolevel()", async function () { - const f = ["bladeburner", "getActionAutolevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setActionAutolevel()", async function () { - const f = ["bladeburner", "setActionAutolevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setActionLevel()", async function () { - const f = ["bladeburner", "setActionLevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getRank()", async function () { - const f = ["bladeburner", "getRank"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getBlackOpRank()", async function () { - const f = ["bladeburner", "getBlackOpRank"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getSkillPoints()", async function () { - const f = ["bladeburner", "getSkillPoints"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getSkillLevel()", async function () { - const f = ["bladeburner", "getSkillLevel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getSkillUpgradeCost()", async function () { - const f = ["bladeburner", "getSkillUpgradeCost"]; - await testNonzeroDynamicRamCost(f); - }); - - it("upgradeSkill()", async function () { - const f = ["bladeburner", "upgradeSkill"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getTeamSize()", async function () { - const f = ["bladeburner", "getTeamSize"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setTeamSize()", async function () { - const f = ["bladeburner", "setTeamSize"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getCityEstimatedPopulation()", async function () { - const f = ["bladeburner", "getCityEstimatedPopulation"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getCityChaos()", async function () { - const f = ["bladeburner", "getCityChaos"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getCity()", async function () { - const f = ["bladeburner", "getCity"]; - await testNonzeroDynamicRamCost(f); - }); - - it("switchCity()", async function () { - const f = ["bladeburner", "switchCity"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getStamina()", async function () { - const f = ["bladeburner", "getStamina"]; - await testNonzeroDynamicRamCost(f); - }); - - it("joinBladeburnerFaction()", async function () { - const f = ["bladeburner", "joinBladeburnerFaction"]; - await testNonzeroDynamicRamCost(f); - }); - - it("joinBladeburnerDivision()", async function () { - const f = ["bladeburner", "joinBladeburnerDivision"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getBonusTime()", async function () { - const f = ["bladeburner", "getBonusTime"]; - await testZeroDynamicRamCost(f); - }); - }); - - describe("Gang API", function () { - it("getMemberNames()", async function () { - const f = ["gang", "getMemberNames"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getGangInformation()", async function () { - const f = ["gang", "getGangInformation"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getOtherGangInformation()", async function () { - const f = ["gang", "getOtherGangInformation"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getMemberInformation()", async function () { - const f = ["gang", "getMemberInformation"]; - await testNonzeroDynamicRamCost(f); - }); - - it("canRecruitMember()", async function () { - const f = ["gang", "canRecruitMember"]; - await testNonzeroDynamicRamCost(f); - }); - - it("recruitMember()", async function () { - const f = ["gang", "recruitMember"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getTaskNames()", async function () { - const f = ["gang", "getTaskNames"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setMemberTask()", async function () { - const f = ["gang", "setMemberTask"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getEquipmentNames()", async function () { - const f = ["gang", "getEquipmentNames"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getEquipmentCost()", async function () { - const f = ["gang", "getEquipmentCost"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getEquipmentType()", async function () { - const f = ["gang", "getEquipmentType"]; - await testNonzeroDynamicRamCost(f); - }); - - it("purchaseEquipment()", async function () { - const f = ["gang", "purchaseEquipment"]; - await testNonzeroDynamicRamCost(f); - }); - - it("ascendMember()", async function () { - const f = ["gang", "ascendMember"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setTerritoryWarfare()", async function () { - const f = ["gang", "setTerritoryWarfare"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getChanceToWinClash()", async function () { - const f = ["gang", "getChanceToWinClash"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getBonusTime()", async function () { - const f = ["gang", "getBonusTime"]; - await testZeroDynamicRamCost(f); - }); - }); - - describe("Coding Contract API", function () { - it("attempt()", async function () { - const f = ["codingcontract", "attempt"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getContractType()", async function () { - const f = ["codingcontract", "getContractType"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getDescription()", async function () { - const f = ["codingcontract", "getDescription"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getData()", async function () { - const f = ["codingcontract", "getData"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getNumTriesRemaining()", async function () { - const f = ["codingcontract", "getNumTriesRemaining"]; - await testNonzeroDynamicRamCost(f); - }); - }); - - describe("Sleeve API", function () { - it("getNumSleeves()", async function () { - const f = ["sleeve", "getNumSleeves"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getSleeveStats()", async function () { - const f = ["sleeve", "getSleeveStats"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getInformation()", async function () { - const f = ["sleeve", "getInformation"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getTask()", async function () { - const f = ["sleeve", "getTask"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setToShockRecovery()", async function () { - const f = ["sleeve", "setToShockRecovery"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setToSynchronize()", async function () { - const f = ["sleeve", "setToSynchronize"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setToCommitCrime()", async function () { - const f = ["sleeve", "setToCommitCrime"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setToFactionWork()", async function () { - const f = ["sleeve", "setToFactionWork"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setToCompanyWork()", async function () { - const f = ["sleeve", "setToCompanyWork"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setToUniversityCourse()", async function () { - const f = ["sleeve", "setToUniversityCourse"]; - await testNonzeroDynamicRamCost(f); - }); - - it("setToGymWorkout()", async function () { - const f = ["sleeve", "setToGymWorkout"]; - await testNonzeroDynamicRamCost(f); - }); - - it("travel()", async function () { - const f = ["sleeve", "travel"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getSleeveAugmentations()", async function () { - const f = ["sleeve", "getSleeveAugmentations"]; - await testNonzeroDynamicRamCost(f); - }); - - it("getSleevePurchasableAugs()", async function () { - const f = ["sleeve", "getSleevePurchasableAugs"]; - await testNonzeroDynamicRamCost(f); - }); - - it("purchaseSleeveAug()", async function () { - const f = ["sleeve", "purchaseSleeveAug"]; - await testNonzeroDynamicRamCost(f); - }); - }); -}); diff --git a/test/jest/Netscript/RamCalculation.test.ts b/test/jest/Netscript/RamCalculation.test.ts new file mode 100644 index 000000000..47672676d --- /dev/null +++ b/test/jest/Netscript/RamCalculation.test.ts @@ -0,0 +1,217 @@ +import { Player } from "../../../src/Player"; +import { NetscriptFunctions } from "../../../src/NetscriptFunctions"; +import { RamCosts, getRamCost, RamCostConstants } from "../../../src/Netscript/RamCostGenerator"; +import { Environment } from "../../../src/Netscript/Environment"; +import { RunningScript } from "../../../src/Script/RunningScript"; +import { Script } from "../../../src/Script/Script"; +import { WorkerScript } from "../../../src/Netscript/WorkerScript"; +import { calculateRamUsage } from "../../../src/Script/RamCalculations"; + +describe("Netscript RAM Calculation/Generation Tests", function () { + Player.sourceFiles[0] = { n: 4, lvl: 3 }; + // For simulating costs of singularity functions. + const ScriptBaseCost = RamCostConstants.ScriptBaseRamCost; + const script = new Script(); + /** Creates a RunningScript object which calculates static ram usage */ + function createRunningScript(code: string) { + script.code = code; + script.updateRamUsage([]); + const runningScript = new RunningScript(script); + return runningScript; + } + + type potentiallyAsyncFunction = (arg?: unknown) => { catch?: potentiallyAsyncFunction }; + /** Runs a Netscript function and properly catches an error even if it returns promise. */ + function tryFunction(fn: potentiallyAsyncFunction) { + try { + fn()?.catch?.(() => undefined); + } catch {} + } + + let runningScript = createRunningScript(""); + //Since it is expensive to create a workerscript and wrap the ns API, this is done once + const workerScript = { + args: [] as string[], + code: "", + delay: null, + dynamicLoadedFns: {}, + dynamicRamUsage: RamCostConstants.ScriptBaseRamCost, + env: new Environment(), + ramUsage: runningScript.ramUsage, + scriptRef: runningScript, + }; + const ns = NetscriptFunctions(workerScript as WorkerScript); + + /** + * Tests that: + * 1. A function has non-zero RAM cost, or zero if it is flagged as zero cost. + * 2. Running the function properly updates the MockWorkerScript's dynamic RAM calculation + * 3. Running multiple calls of the function does not result in additional RAM cost + * @param {string[]} fnDesc - describes the name of the function being tested, + * including the namespace(s). e.g. ["gang", "getMemberNames"] + */ + function testDynamicRamCost(fnDesc: string[], zero: boolean = false) { + const expected = getRamCost(...fnDesc); + zero ? expect(expected).toEqual(0) : expect(expected).toBeGreaterThan(0); + } + + function dynamicCheck(fnPath: string[], expectedRamCost: number) { + const code = `${fnPath.join(".")}();\n`.repeat(3); + const fnName = fnPath[fnPath.length - 1]; + + // update our existing WorkerScript + runningScript = createRunningScript(code); + workerScript.code = code; + workerScript.scriptRef = runningScript; + workerScript.ramUsage = workerScript.scriptRef.ramUsage; + workerScript.dynamicRamUsage = ScriptBaseCost; + workerScript.env = new Environment(); + workerScript.dynamicLoadedFns = {}; + workerScript.env.vars = ns; + + // Run the function through the workerscript's args + const fn = fnPath.reduce((prev, curr) => prev[curr], ns as any); + + if (typeof fn === "function") { + tryFunction(fn); + tryFunction(fn); + tryFunction(fn); + } else { + throw new Error(`Invalid function specified: [${fnPath.toString()}]`); + } + + expect(workerScript.dynamicLoadedFns).toHaveProperty(fnName); + expect(workerScript.dynamicRamUsage - ScriptBaseCost).toBeCloseTo(expectedRamCost, 5); + expect(workerScript.dynamicRamUsage).toBeCloseTo(runningScript.ramUsage, 5); + } + + function testFunctionExpectZero(fnPath: string[]) { + const wholeFn = `${fnPath.join(".")}()`; + describe(wholeFn, () => { + it("Zero Ram Static Check", () => { + const ramCost = getRamCost(...fnPath); + expect(ramCost).toEqual(0); + const code = wholeFn; + const staticCost = calculateRamUsage(code, []).cost; + expect(staticCost).toEqual(ScriptBaseCost); + }); + it("Zero Ram Dynamic check", () => dynamicCheck(fnPath, 0)); + }); + } + + function testFunctionExpectNonzero(fnPath: string[]) { + const wholeFn = `${fnPath.join(".")}()`; + const ramCost = getRamCost(...fnPath); + describe(wholeFn, () => { + it("Static Check", () => { + expect(ramCost).toBeGreaterThan(0); + const code = wholeFn; + const staticCost = calculateRamUsage(code, []).cost; + expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost, 5); + }); + it("Dynamic Check", () => dynamicCheck(fnPath, ramCost)); + }); + } + + type singularityData = { fnPath: string[]; baseCost: number }; + function testSingularityFunctions(data: singularityData[]) { + const sf4 = Player.sourceFiles[0]; + data.forEach(({ fnPath, baseCost }) => { + const wholeFn = `${fnPath.join(".")}()`; + describe(wholeFn, () => { + it("SF4.3", () => { + sf4.lvl = 3; + const ramCost = getRamCost(...fnPath); + expect(ramCost).toEqual(baseCost); + const code = wholeFn; + const staticCost = calculateRamUsage(code, []).cost; + expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost); + dynamicCheck(fnPath, baseCost); + }); + it("SF4.2", () => { + sf4.lvl = 2; + const ramCost = getRamCost(...fnPath); + expect(ramCost).toBeCloseTo(baseCost * 4, 5); + const code = wholeFn; + const staticCost = calculateRamUsage(code, []).cost; + expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost); + dynamicCheck(fnPath, ramCost); + }); + it("SF4.1", () => { + sf4.lvl = 1; + const ramCost = getRamCost(...fnPath); + expect(ramCost).toBeCloseTo(baseCost * 16, 5); + const code = wholeFn; + const staticCost = calculateRamUsage(code, []).cost; + expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost); + dynamicCheck(fnPath, ramCost); + }); + }); + }); + } + + type NSLayer = { + [key: string]: NSLayer | unknown[] | (() => unknown); + }; + type RamLayer = { + [key: string]: number | (() => number); + }; + function testLayer(nsLayer: NSLayer, ramLayer: RamLayer, path: string[]) { + const zeroCostFunctions = Object.entries(nsLayer) + .filter(([key, val]) => ramLayer[key] === 0 && typeof val === "function") + .map(([key]) => [...path, key]); + zeroCostFunctions.forEach(testFunctionExpectZero); + + const nonzeroCostFunctions = Object.entries(nsLayer) + .filter(([key, val]) => ramLayer[key] > 0 && typeof val === "function") + .map(([key]) => [...path, key]); + nonzeroCostFunctions.forEach(testFunctionExpectNonzero); + } + + describe("Top level ns functions", function () { + const nsScope = ns as unknown as NSLayer; + const ramScope = RamCosts as unknown as RamLayer; + testLayer(nsScope, ramScope, []); + }); + + describe("TIX API (stock) functions", function () { + const nsScope = ns.stock as unknown as NSLayer; + const ramScope = RamCosts.stock as unknown as RamLayer; + testLayer(nsScope, ramScope, ["stock"]); + }); + + describe("Bladeburner API (bladeburner) functions", function () { + const nsScope = ns.bladeburner as unknown as NSLayer; + const ramScope = RamCosts.bladeburner as unknown as RamLayer; + testLayer(nsScope, ramScope, ["bladeburner"]); + }); + + describe("Gang API (gang) functions", function () { + const nsScope = ns.gang as unknown as NSLayer; + const ramScope = RamCosts.gang as unknown as RamLayer; + testLayer(nsScope, ramScope, ["gang"]); + }); + + describe("Coding Contract API (codingcontract) functions", function () { + const nsScope = ns.codingcontract as unknown as NSLayer; + const ramScope = RamCosts.codingcontract as unknown as RamLayer; + testLayer(nsScope, ramScope, ["codingcontract"]); + }); + + describe("Sleeve API (sleeve) functions", function () { + const nsScope = ns.sleeve as unknown as NSLayer; + const ramScope = RamCosts.sleeve as unknown as RamLayer; + testLayer(nsScope, ramScope, ["sleeve"]); + }); + + //Singularity functions are tested in a different way because they also check SF4 level effect + describe("ns.singularity functions", function () { + const singularityFunctions = Object.entries(RamCosts.singularity).map(([key, val]) => { + return { + fnPath: ["singularity", key], + baseCost: (val as () => number)(), + }; + }); + testSingularityFunctions(singularityFunctions); + }); +}); diff --git a/test/jest/Netscript/StaticRamCalculation.test.ts b/test/jest/Netscript/StaticRamCalculation.test.ts deleted file mode 100644 index c56cc7f43..000000000 --- a/test/jest/Netscript/StaticRamCalculation.test.ts +++ /dev/null @@ -1,1164 +0,0 @@ -import { Player } from "../../../src/Player"; -import { getRamCost, RamCostConstants } from "../../../src/Netscript/RamCostGenerator"; -import { calculateRamUsage } from "../../../src/Script/RamCalculations"; - -const ScriptBaseCost = RamCostConstants.ScriptBaseRamCost; -const HacknetNamespaceCost = RamCostConstants.ScriptHacknetNodesRamCost; - -describe("Netscript Static RAM Calculation/Generation Tests", function () { - // Tests numeric equality, allowing for floating point imprecision - /** - * - * @param {number} val - * @param {number} expected - */ - function testEquality(val: number, expected: number) { - expect(val).toBeGreaterThanOrEqual(expected - 100 * Number.EPSILON); - expect(val).toBeLessThanOrEqual(expected + 100 * Number.EPSILON); - } - - /** - * Tests that: - * 1. A function has non-zero RAM cost - * 2. The calculator and the generator result in equal values - * 3. Running multiple calls of the function does not result in additional RAM cost - * @param {string[]} fnDesc - describes the name of the function being tested, - * including the namespace(s). e.g. ["gang", "getMemberNames"] - */ - async function expectNonZeroRamCost(fnDesc: string[]) { - const expected = getRamCost(...fnDesc); - expect(expected).toBeGreaterThan(0); - - const code = fnDesc.join(".") + "(); "; - - const calculated = calculateRamUsage(code, []).cost; - testEquality(calculated, expected + ScriptBaseCost); - - const multipleCallsCode = code.repeat(3); - const multipleCallsCalculated = calculateRamUsage(multipleCallsCode, []).cost; - expect(multipleCallsCalculated).toEqual(calculated); - } - - /** - * Tests that: - * 1. A function has zero RAM cost - * 2. The calculator and the generator result in equal values - * 3. Running multiple calls of the function does not result in additional RAM cost - * @param {string[]} fnDesc - describes the name of the function being tested, - * including the namespace(s). e.g. ["gang", "getMemberNames"] - */ - async function expectZeroRamCost(fnDesc: string[]) { - const expected = getRamCost(...fnDesc); - expect(expected).toEqual(0); - - const code = fnDesc.join(".") + "(); "; - const calculated = calculateRamUsage(code, []).cost; - testEquality(calculated, ScriptBaseCost); - - const multipleCallsCalculated = calculateRamUsage(code, []).cost; - expect(multipleCallsCalculated).toEqual(ScriptBaseCost); - } - - function SF4Cost(cost: number) { - if (Player.bitNodeN === 4) return cost; - const sf4 = Player.sourceFileLvl(4); - if (sf4 <= 1) return cost * 16; - if (sf4 === 2) return cost * 4; - return cost; - } - - /** - * Tests that: - * 1. A function has a specific RAM cost - * 2. The calculator and the generator result in equal values - * 3. Running multiple calls of the function does not result in additional RAM cost - * @param {string[]} fnDesc - describes the name of the function being tested, - * including the namespace(s). e.g. ["gang", "getMemberNames"] - * @param {number} cost - expected cost - */ - async function expectSpecificRamCost(fnDesc: string[], cost: number) { - const expected = getRamCost(...fnDesc); - expect(expected).toEqual(SF4Cost(cost)); - - const code = fnDesc.join(".") + "(); "; - const calculated = calculateRamUsage(code, []).cost; - testEquality(calculated, ScriptBaseCost + SF4Cost(cost)); - - const multipleCallsCalculated = calculateRamUsage(code, []).cost; - expect(multipleCallsCalculated).toEqual(ScriptBaseCost + SF4Cost(cost)); - } - - describe("Basic Functions", function () { - it("hack()", async function () { - const f = ["hack"]; - await expectNonZeroRamCost(f); - }); - - it("grow()", async function () { - const f = ["grow"]; - await expectNonZeroRamCost(f); - }); - - it("weaken()", async function () { - const f = ["weaken"]; - await expectNonZeroRamCost(f); - }); - - it("hackAnalyzeThreads()", async function () { - const f = ["hackAnalyzeThreads"]; - await expectNonZeroRamCost(f); - }); - - it("hackAnalyze()", async function () { - const f = ["hackAnalyze"]; - await expectNonZeroRamCost(f); - }); - - it("hackAnalyzeChance()", async function () { - const f = ["hackAnalyzeChance"]; - await expectNonZeroRamCost(f); - }); - - it("growthAnalyze()", async function () { - const f = ["growthAnalyze"]; - await expectNonZeroRamCost(f); - }); - - it("sleep()", async function () { - const f = ["sleep"]; - await expectZeroRamCost(f); - }); - - it("print()", async function () { - const f = ["print"]; - await expectZeroRamCost(f); - }); - - it("tprint()", async function () { - const f = ["tprint"]; - await expectZeroRamCost(f); - }); - - it("clearLog()", async function () { - const f = ["clearLog"]; - await expectZeroRamCost(f); - }); - - it("disableLog()", async function () { - const f = ["disableLog"]; - await expectZeroRamCost(f); - }); - - it("enableLog()", async function () { - const f = ["enableLog"]; - await expectZeroRamCost(f); - }); - - it("isLogEnabled()", async function () { - const f = ["isLogEnabled"]; - await expectZeroRamCost(f); - }); - - it("getScriptLogs()", async function () { - const f = ["getScriptLogs"]; - await expectZeroRamCost(f); - }); - - it("scan()", async function () { - const f = ["scan"]; - await expectNonZeroRamCost(f); - }); - - it("nuke()", async function () { - const f = ["nuke"]; - await expectNonZeroRamCost(f); - }); - - it("brutessh()", async function () { - const f = ["brutessh"]; - await expectNonZeroRamCost(f); - }); - - it("ftpcrack()", async function () { - const f = ["ftpcrack"]; - await expectNonZeroRamCost(f); - }); - - it("relaysmtp()", async function () { - const f = ["relaysmtp"]; - await expectNonZeroRamCost(f); - }); - - it("httpworm()", async function () { - const f = ["httpworm"]; - await expectNonZeroRamCost(f); - }); - - it("sqlinject()", async function () { - const f = ["sqlinject"]; - await expectNonZeroRamCost(f); - }); - - it("run()", async function () { - const f = ["run"]; - await expectNonZeroRamCost(f); - }); - - it("exec()", async function () { - const f = ["exec"]; - await expectNonZeroRamCost(f); - }); - - it("spawn()", async function () { - const f = ["spawn"]; - await expectNonZeroRamCost(f); - }); - - it("kill()", async function () { - const f = ["kill"]; - await expectNonZeroRamCost(f); - }); - - it("killall()", async function () { - const f = ["killall"]; - await expectNonZeroRamCost(f); - }); - - it("exit()", async function () { - const f = ["exit"]; - await expectZeroRamCost(f); - }); - - it("scp()", async function () { - const f = ["scp"]; - await expectNonZeroRamCost(f); - }); - - it("ls()", async function () { - const f = ["ls"]; - await expectNonZeroRamCost(f); - }); - - it("ps()", async function () { - const f = ["ps"]; - await expectNonZeroRamCost(f); - }); - - it("hasRootAccess()", async function () { - const f = ["hasRootAccess"]; - await expectNonZeroRamCost(f); - }); - - it("getHostname()", async function () { - const f = ["getHostname"]; - await expectNonZeroRamCost(f); - }); - - it("getHackingLevel()", async function () { - const f = ["getHackingLevel"]; - await expectNonZeroRamCost(f); - }); - - it("getHackingMultipliers()", async function () { - const f = ["getHackingMultipliers"]; - await expectNonZeroRamCost(f); - }); - - it("getHacknetMultipliers()", async function () { - const f = ["getHacknetMultipliers"]; - await expectNonZeroRamCost(f); - }); - - it("getServerMoneyAvailable()", async function () { - const f = ["getServerMoneyAvailable"]; - await expectNonZeroRamCost(f); - }); - - it("getServerMaxMoney()", async function () { - const f = ["getServerMaxMoney"]; - await expectNonZeroRamCost(f); - }); - - it("getServerGrowth()", async function () { - const f = ["getServerGrowth"]; - await expectNonZeroRamCost(f); - }); - - it("getServerSecurityLevel()", async function () { - const f = ["getServerSecurityLevel"]; - await expectNonZeroRamCost(f); - }); - - it("getServerBaseSecurityLevel()", async function () { - const f = ["getServerBaseSecurityLevel"]; - await expectNonZeroRamCost(f); - }); - - it("getServerMinSecurityLevel()", async function () { - const f = ["getServerMinSecurityLevel"]; - await expectNonZeroRamCost(f); - }); - - it("getServerRequiredHackingLevel()", async function () { - const f = ["getServerRequiredHackingLevel"]; - await expectNonZeroRamCost(f); - }); - - it("getServerNumPortsRequired()", async function () { - const f = ["getServerNumPortsRequired"]; - await expectNonZeroRamCost(f); - }); - - it("getServerRam()", async function () { - const f = ["getServerRam"]; - await expectNonZeroRamCost(f); - }); - - it("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); - }); - - it("fileExists()", async function () { - const f = ["fileExists"]; - await expectNonZeroRamCost(f); - }); - - it("isRunning()", async function () { - const f = ["isRunning"]; - await expectNonZeroRamCost(f); - }); - - it("getPurchasedServerCost()", async function () { - const f = ["getPurchasedServerCost"]; - await expectNonZeroRamCost(f); - }); - - it("purchaseServer()", async function () { - const f = ["purchaseServer"]; - await expectNonZeroRamCost(f); - }); - - it("deleteServer()", async function () { - const f = ["deleteServer"]; - await expectNonZeroRamCost(f); - }); - - it("getPurchasedServers()", async function () { - const f = ["getPurchasedServers"]; - await expectNonZeroRamCost(f); - }); - - it("getPurchasedServerLimit()", async function () { - const f = ["getPurchasedServerLimit"]; - await expectNonZeroRamCost(f); - }); - - it("getPurchasedServerMaxRam()", async function () { - const f = ["getPurchasedServerMaxRam"]; - await expectNonZeroRamCost(f); - }); - - it("write()", async function () { - const f = ["write"]; - await expectZeroRamCost(f); - }); - - it("tryWritePort()", async function () { - const f = ["tryWritePort"]; - await expectZeroRamCost(f); - }); - - it("read()", async function () { - const f = ["read"]; - await expectZeroRamCost(f); - }); - - it("peek()", async function () { - const f = ["peek"]; - await expectZeroRamCost(f); - }); - - it("clear()", async function () { - const f = ["clear"]; - await expectZeroRamCost(f); - }); - - it("getPortHandle()", async function () { - const f = ["getPortHandle"]; - await expectZeroRamCost(f); - }); - - it("rm()", async function () { - const f = ["rm"]; - await expectNonZeroRamCost(f); - }); - - it("scriptRunning()", async function () { - const f = ["scriptRunning"]; - await expectNonZeroRamCost(f); - }); - - it("scriptKill()", async function () { - const f = ["scriptKill"]; - await expectNonZeroRamCost(f); - }); - - it("getScriptName()", async function () { - const f = ["getScriptName"]; - await expectZeroRamCost(f); - }); - - it("getScriptRam()", async function () { - const f = ["getScriptRam"]; - await expectNonZeroRamCost(f); - }); - - it("getHackTime()", async function () { - const f = ["getHackTime"]; - await expectNonZeroRamCost(f); - }); - - it("getGrowTime()", async function () { - const f = ["getGrowTime"]; - await expectNonZeroRamCost(f); - }); - - it("getWeakenTime()", async function () { - const f = ["getWeakenTime"]; - await expectNonZeroRamCost(f); - }); - - it("getScriptIncome()", async function () { - const f = ["getScriptIncome"]; - await expectNonZeroRamCost(f); - }); - - it("getScriptExpGain()", async function () { - const f = ["getScriptExpGain"]; - await expectNonZeroRamCost(f); - }); - - it("getRunningScript()", async function () { - const f = ["getRunningScript"]; - await expectNonZeroRamCost(f); - }); - - it("getTimeSinceLastAug()", async function () { - const f = ["getTimeSinceLastAug"]; - await expectNonZeroRamCost(f); - }); - - it("sprintf()", async function () { - const f = ["sprintf"]; - await expectZeroRamCost(f); - }); - - it("vsprintf()", async function () { - const f = ["vsprintf"]; - await expectZeroRamCost(f); - }); - - it("nFormat()", async function () { - const f = ["nFormat"]; - await expectZeroRamCost(f); - }); - - it("prompt()", async function () { - const f = ["prompt"]; - await expectZeroRamCost(f); - }); - - it("wget()", async function () { - const f = ["wget"]; - await expectZeroRamCost(f); - }); - - it("getFavorToDonate()", async function () { - const f = ["getFavorToDonate"]; - await expectNonZeroRamCost(f); - }); - - it("goToLocation()", async function () { - const f = ["goToLocation"]; - await expectSpecificRamCost(f, RamCostConstants.ScriptSingularityFn3RamCost); - }); - }); - - describe("Advanced Functions", function () { - it("getBitNodeMultipliers()", async function () { - const f = ["getBitNodeMultipliers"]; - await expectNonZeroRamCost(f); - }); - }); - - describe("Hacknet Node API", function () { - // The Hacknet Node API RAM cost is a bit different because - // it's just a one-time cost to access the 'hacknet' namespace. - // Otherwise, all functions cost 0 RAM - const apiFunctions = [ - "numNodes", - "purchaseNode", - "getPurchaseNodeCost", - "getNodeStats", - "upgradeLevel", - "upgradeRam", - "upgradeCore", - "upgradeCache", - "getLevelUpgradeCost", - "getRamUpgradeCost", - "getCoreUpgradeCost", - "getCacheUpgradeCost", - "numHashes", - "hashCost", - "spendHashes", - ]; - it("should have zero RAM cost for all functions", function () { - for (const fn of apiFunctions) { - expect(getRamCost("hacknet", fn)).toEqual(0); - } - }); - - it("should incur a one time cost of for accesing the namespace", async function () { - let code = ""; - for (const fn of apiFunctions) { - code += "hacknet." + fn + "(); "; - } - - const calculated = calculateRamUsage(code, []); - testEquality(calculated.cost, ScriptBaseCost + HacknetNamespaceCost); - }); - }); - - describe("TIX API", function () { - it("stock.getSymbols()", async function () { - const f = ["stock", "getSymbols"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getPrice()", async function () { - const f = ["stock", "getPrice"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getAskPrice()", async function () { - const f = ["stock", "getAskPrice"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getBidPrice()", async function () { - const f = ["stock", "getBidPrice"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getPosition()", async function () { - const f = ["stock", "getPosition"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getMaxShares()", async function () { - const f = ["stock", "getMaxShares"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getPurchaseCost()", async function () { - const f = ["stock", "getPurchaseCost"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getSaleGain()", async function () { - const f = ["stock", "getSaleGain"]; - await expectNonZeroRamCost(f); - }); - - it("stock.buyStock()", async function () { - const f = ["stock", "buyStock"]; - await expectNonZeroRamCost(f); - }); - - it("stock.sellStock()", async function () { - const f = ["stock", "sellStock"]; - await expectNonZeroRamCost(f); - }); - - it("stock.sellShort()", async function () { - const f = ["stock", "sellShort"]; - await expectNonZeroRamCost(f); - }); - - it("stock.placeOrder()", async function () { - const f = ["stock", "placeOrder"]; - await expectNonZeroRamCost(f); - }); - - it("stock.cancelOrder()", async function () { - const f = ["stock", "cancelOrder"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getOrders()", async function () { - const f = ["stock", "getOrders"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getVolatility()", async function () { - const f = ["stock", "getVolatility"]; - await expectNonZeroRamCost(f); - }); - - it("stock.getForecast()", async function () { - const f = ["stock", "getForecast"]; - await expectNonZeroRamCost(f); - }); - - it("stock.purchase4SMarketData()", async function () { - const f = ["stock", "purchase4SMarketData"]; - await expectNonZeroRamCost(f); - }); - - it("stock.purchase4SMarketDataTixApi()", async function () { - const f = ["stock", "purchase4SMarketDataTixApi"]; - await expectNonZeroRamCost(f); - }); - }); - - describe("Singularity Functions", function () { - it("universityCourse()", async function () { - const f = ["universityCourse"]; - await expectNonZeroRamCost(f); - }); - - it("gymWorkout()", async function () { - const f = ["gymWorkout"]; - await expectNonZeroRamCost(f); - }); - - it("travelToCity()", async function () { - const f = ["travelToCity"]; - await expectNonZeroRamCost(f); - }); - - it("purchaseTor()", async function () { - const f = ["purchaseTor"]; - await expectNonZeroRamCost(f); - }); - - it("purchaseProgram()", async function () { - const f = ["purchaseProgram"]; - await expectNonZeroRamCost(f); - }); - - it("isBusy()", async function () { - const f = ["isBusy"]; - await expectNonZeroRamCost(f); - }); - - it("stopAction()", async function () { - const f = ["stopAction"]; - await expectNonZeroRamCost(f); - }); - - it("getDarkwebPrograms()", async function () { - const f = ["getDarkwebPrograms"]; - await expectNonZeroRamCost(f); - }); - - it("getDarkwebProgramCost()", async function () { - const f = ["getDarkwebProgramCost"]; - await expectNonZeroRamCost(f); - }); - - it("upgradeHomeRam()", async function () { - const f = ["upgradeHomeRam"]; - await expectNonZeroRamCost(f); - }); - - it("getUpgradeHomeRamCost()", async function () { - const f = ["getUpgradeHomeRamCost"]; - await expectNonZeroRamCost(f); - }); - - it("workForCompany()", async function () { - const f = ["workForCompany"]; - await expectNonZeroRamCost(f); - }); - - it("applyToCompany()", async function () { - const f = ["applyToCompany"]; - await expectNonZeroRamCost(f); - }); - - it("getCompanyRep()", async function () { - const f = ["getCompanyRep"]; - await expectNonZeroRamCost(f); - }); - - it("getCompanyFavor()", async function () { - const f = ["getCompanyFavor"]; - await expectNonZeroRamCost(f); - }); - - it("getCompanyFavorGain()", async function () { - const f = ["getCompanyFavorGain"]; - await expectNonZeroRamCost(f); - }); - - it("checkFactionInvitations()", async function () { - const f = ["checkFactionInvitations"]; - await expectNonZeroRamCost(f); - }); - - it("joinFaction()", async function () { - const f = ["joinFaction"]; - await expectNonZeroRamCost(f); - }); - - it("workForFaction()", async function () { - const f = ["workForFaction"]; - await expectNonZeroRamCost(f); - }); - - it("getFactionRep()", async function () { - const f = ["getFactionRep"]; - await expectNonZeroRamCost(f); - }); - - it("getFactionFavor()", async function () { - const f = ["getFactionFavor"]; - await expectNonZeroRamCost(f); - }); - - it("getFactionFavorGain()", async function () { - const f = ["getFactionFavorGain"]; - await expectNonZeroRamCost(f); - }); - - it("donateToFaction()", async function () { - const f = ["donateToFaction"]; - await expectNonZeroRamCost(f); - }); - - it("createProgram()", async function () { - const f = ["createProgram"]; - await expectNonZeroRamCost(f); - }); - - it("commitCrime()", async function () { - const f = ["commitCrime"]; - await expectNonZeroRamCost(f); - }); - - it("getCrimeChance()", async function () { - const f = ["getCrimeChance"]; - await expectNonZeroRamCost(f); - }); - - it("getOwnedAugmentations()", async function () { - const f = ["getOwnedAugmentations"]; - await expectNonZeroRamCost(f); - }); - - it("getOwnedSourceFiles()", async function () { - const f = ["getOwnedSourceFiles"]; - await expectNonZeroRamCost(f); - }); - - it("getAugmentationsFromFaction()", async function () { - const f = ["getAugmentationsFromFaction"]; - await expectNonZeroRamCost(f); - }); - - it("getAugmentationCost()", async function () { - const f = ["getAugmentationCost"]; - await expectNonZeroRamCost(f); - }); - - it("getAugmentationPrereq()", async function () { - const f = ["getAugmentationPrereq"]; - await expectNonZeroRamCost(f); - }); - - it("getAugmentationPrice()", async function () { - const f = ["getAugmentationPrice"]; - await expectNonZeroRamCost(f); - }); - - it("getAugmentationRepReq()", async function () { - const f = ["getAugmentationRepReq"]; - await expectNonZeroRamCost(f); - }); - - it("purchaseAugmentation()", async function () { - const f = ["purchaseAugmentation"]; - await expectNonZeroRamCost(f); - }); - - it("installAugmentations()", async function () { - const f = ["installAugmentations"]; - await expectNonZeroRamCost(f); - }); - }); - - describe("Bladeburner API", function () { - it("getContractNames()", async function () { - const f = ["bladeburner", "getContractNames"]; - await expectNonZeroRamCost(f); - }); - - it("getOperationNames()", async function () { - const f = ["bladeburner", "getOperationNames"]; - await expectNonZeroRamCost(f); - }); - - it("getBlackOpNames()", async function () { - const f = ["bladeburner", "getBlackOpNames"]; - await expectNonZeroRamCost(f); - }); - - it("getGeneralActionNames()", async function () { - const f = ["bladeburner", "getGeneralActionNames"]; - await expectNonZeroRamCost(f); - }); - - it("getSkillNames()", async function () { - const f = ["bladeburner", "getSkillNames"]; - await expectNonZeroRamCost(f); - }); - - it("startAction()", async function () { - const f = ["bladeburner", "startAction"]; - await expectNonZeroRamCost(f); - }); - - it("stopBladeburnerAction()", async function () { - const f = ["bladeburner", "stopBladeburnerAction"]; - await expectNonZeroRamCost(f); - }); - - it("getCurrentAction()", async function () { - const f = ["bladeburner", "getCurrentAction"]; - await expectNonZeroRamCost(f); - }); - - it("getActionTime()", async function () { - const f = ["bladeburner", "getActionTime"]; - await expectNonZeroRamCost(f); - }); - - it("getActionEstimatedSuccessChance()", async function () { - const f = ["bladeburner", "getActionEstimatedSuccessChance"]; - await expectNonZeroRamCost(f); - }); - - it("getActionRepGain()", async function () { - const f = ["bladeburner", "getActionRepGain"]; - await expectNonZeroRamCost(f); - }); - - it("getActionCountRemaining()", async function () { - const f = ["bladeburner", "getActionCountRemaining"]; - await expectNonZeroRamCost(f); - }); - - it("getActionMaxLevel()", async function () { - const f = ["bladeburner", "getActionMaxLevel"]; - await expectNonZeroRamCost(f); - }); - - it("getActionCurrentLevel()", async function () { - const f = ["bladeburner", "getActionCurrentLevel"]; - await expectNonZeroRamCost(f); - }); - - it("getActionAutolevel()", async function () { - const f = ["bladeburner", "getActionAutolevel"]; - await expectNonZeroRamCost(f); - }); - - it("setActionAutolevel()", async function () { - const f = ["bladeburner", "setActionAutolevel"]; - await expectNonZeroRamCost(f); - }); - - it("setActionLevel()", async function () { - const f = ["bladeburner", "setActionLevel"]; - await expectNonZeroRamCost(f); - }); - - it("getRank()", async function () { - const f = ["bladeburner", "getRank"]; - await expectNonZeroRamCost(f); - }); - - it("getBlackOpRank()", async function () { - const f = ["bladeburner", "getBlackOpRank"]; - await expectNonZeroRamCost(f); - }); - - it("getSkillPoints()", async function () { - const f = ["bladeburner", "getSkillPoints"]; - await expectNonZeroRamCost(f); - }); - - it("getSkillLevel()", async function () { - const f = ["bladeburner", "getSkillLevel"]; - await expectNonZeroRamCost(f); - }); - - it("getSkillUpgradeCost()", async function () { - const f = ["bladeburner", "getSkillUpgradeCost"]; - await expectNonZeroRamCost(f); - }); - - it("upgradeSkill()", async function () { - const f = ["bladeburner", "upgradeSkill"]; - await expectNonZeroRamCost(f); - }); - - it("getTeamSize()", async function () { - const f = ["bladeburner", "getTeamSize"]; - await expectNonZeroRamCost(f); - }); - - it("setTeamSize()", async function () { - const f = ["bladeburner", "setTeamSize"]; - await expectNonZeroRamCost(f); - }); - - it("getCityEstimatedPopulation()", async function () { - const f = ["bladeburner", "getCityEstimatedPopulation"]; - await expectNonZeroRamCost(f); - }); - - it("getCityChaos()", async function () { - const f = ["bladeburner", "getCityChaos"]; - await expectNonZeroRamCost(f); - }); - - it("getCity()", async function () { - const f = ["bladeburner", "getCity"]; - await expectNonZeroRamCost(f); - }); - - it("switchCity()", async function () { - const f = ["bladeburner", "switchCity"]; - await expectNonZeroRamCost(f); - }); - - it("getStamina()", async function () { - const f = ["bladeburner", "getStamina"]; - await expectNonZeroRamCost(f); - }); - - it("joinBladeburnerFaction()", async function () { - const f = ["bladeburner", "joinBladeburnerFaction"]; - await expectNonZeroRamCost(f); - }); - - it("joinBladeburnerDivision()", async function () { - const f = ["bladeburner", "joinBladeburnerDivision"]; - await expectNonZeroRamCost(f); - }); - - it("getBonusTime()", async function () { - const f = ["bladeburner", "getBonusTime"]; - await expectZeroRamCost(f); - }); - }); - - describe("Gang API", function () { - it("getMemberNames()", async function () { - const f = ["gang", "getMemberNames"]; - await expectNonZeroRamCost(f); - }); - - it("getGangInformation()", async function () { - const f = ["gang", "getGangInformation"]; - await expectNonZeroRamCost(f); - }); - - it("getOtherGangInformation()", async function () { - const f = ["gang", "getOtherGangInformation"]; - await expectNonZeroRamCost(f); - }); - - it("getMemberInformation()", async function () { - const f = ["gang", "getMemberInformation"]; - await expectNonZeroRamCost(f); - }); - - it("canRecruitMember()", async function () { - const f = ["gang", "canRecruitMember"]; - await expectNonZeroRamCost(f); - }); - - it("recruitMember()", async function () { - const f = ["gang", "recruitMember"]; - await expectNonZeroRamCost(f); - }); - - it("getTaskNames()", async function () { - const f = ["gang", "getTaskNames"]; - await expectNonZeroRamCost(f); - }); - - it("setMemberTask()", async function () { - const f = ["gang", "setMemberTask"]; - await expectNonZeroRamCost(f); - }); - - it("getEquipmentNames()", async function () { - const f = ["gang", "getEquipmentNames"]; - await expectNonZeroRamCost(f); - }); - - it("getEquipmentCost()", async function () { - const f = ["gang", "getEquipmentCost"]; - await expectNonZeroRamCost(f); - }); - - it("getEquipmentType()", async function () { - const f = ["gang", "getEquipmentType"]; - await expectNonZeroRamCost(f); - }); - - it("purchaseEquipment()", async function () { - const f = ["gang", "purchaseEquipment"]; - await expectNonZeroRamCost(f); - }); - - it("ascendMember()", async function () { - const f = ["gang", "ascendMember"]; - await expectNonZeroRamCost(f); - }); - - it("setTerritoryWarfare()", async function () { - const f = ["gang", "setTerritoryWarfare"]; - await expectNonZeroRamCost(f); - }); - - it("getChanceToWinClash()", async function () { - const f = ["gang", "getChanceToWinClash"]; - await expectNonZeroRamCost(f); - }); - - it("getBonusTime()", async function () { - const f = ["gang", "getBonusTime"]; - await expectZeroRamCost(f); - }); - }); - - describe("Coding Contract API", function () { - it("attempt()", async function () { - const f = ["codingcontract", "attempt"]; - await expectNonZeroRamCost(f); - }); - - it("getContractType()", async function () { - const f = ["codingcontract", "getContractType"]; - await expectNonZeroRamCost(f); - }); - - it("getDescription()", async function () { - const f = ["codingcontract", "getDescription"]; - await expectNonZeroRamCost(f); - }); - - it("getData()", async function () { - const f = ["codingcontract", "getData"]; - await expectNonZeroRamCost(f); - }); - - it("getNumTriesRemaining()", async function () { - const f = ["codingcontract", "getNumTriesRemaining"]; - await expectNonZeroRamCost(f); - }); - }); - - describe("Sleeve API", function () { - it("getNumSleeves()", async function () { - const f = ["sleeve", "getNumSleeves"]; - await expectNonZeroRamCost(f); - }); - - it("getSleeveStats()", async function () { - const f = ["sleeve", "getSleeveStats"]; - await expectNonZeroRamCost(f); - }); - - it("getInformation()", async function () { - const f = ["sleeve", "getInformation"]; - await expectNonZeroRamCost(f); - }); - - it("getTask()", async function () { - const f = ["sleeve", "getTask"]; - await expectNonZeroRamCost(f); - }); - - it("setToShockRecovery()", async function () { - const f = ["sleeve", "setToShockRecovery"]; - await expectNonZeroRamCost(f); - }); - - it("setToSynchronize()", async function () { - const f = ["sleeve", "setToSynchronize"]; - await expectNonZeroRamCost(f); - }); - - it("setToCommitCrime()", async function () { - const f = ["sleeve", "setToCommitCrime"]; - await expectNonZeroRamCost(f); - }); - - it("setToFactionWork()", async function () { - const f = ["sleeve", "setToFactionWork"]; - await expectNonZeroRamCost(f); - }); - - it("setToCompanyWork()", async function () { - const f = ["sleeve", "setToCompanyWork"]; - await expectNonZeroRamCost(f); - }); - - it("setToUniversityCourse()", async function () { - const f = ["sleeve", "setToUniversityCourse"]; - await expectNonZeroRamCost(f); - }); - - it("setToGymWorkout()", async function () { - const f = ["sleeve", "setToGymWorkout"]; - await expectNonZeroRamCost(f); - }); - - it("travel()", async function () { - const f = ["sleeve", "travel"]; - await expectNonZeroRamCost(f); - }); - - it("getSleeveAugmentations()", async function () { - const f = ["sleeve", "getSleeveAugmentations"]; - await expectNonZeroRamCost(f); - }); - - it("getSleevePurchasableAugs()", async function () { - const f = ["sleeve", "getSleevePurchasableAugs"]; - await expectNonZeroRamCost(f); - }); - - it("purchaseSleeveAug()", async function () { - const f = ["sleeve", "purchaseSleeveAug"]; - await expectNonZeroRamCost(f); - }); - }); -}); From 8bb88a50808e4311079cba507b13a36652ebae28 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Wed, 5 Oct 2022 10:42:07 -0400 Subject: [PATCH 5/8] Better RamCost testing (see desc) * RamCostGenerator will have an error if ramcosts are defined for nonexistent functions, in addition to error if not all functions have ram costs defined * Removed a few random blank comment lines in NetscriptDefinitions.d.ts * RamCalculation.test.ts checks exact expected static and dynamic ram usage from (almost) every function, based on defined RamCosts in RamCostGenerator. --- src/Netscript/RamCostGenerator.ts | 60 +++++------- src/ScriptEditor/NetscriptDefinitions.d.ts | 24 ++--- test/jest/Netscript/RamCalculation.test.ts | 104 ++++++++++++--------- 3 files changed, 95 insertions(+), 93 deletions(-) diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index 280c3b417..2a8fa9dd7 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -1,19 +1,12 @@ import { Player } from "../Player"; +import { NSFull } from "../NetscriptFunctions"; -import { NS as INS } from "../ScriptEditor/NetscriptDefinitions"; -import { INetscriptExtra } from "../NetscriptFunctions/Extra"; - +/** This type assumes any value that isn't an API layer or a function has been omitted (args and enum) */ type RamCostTree = { - [Property in keyof API]: API[Property] extends () => void - ? number | (() => void) - : API[Property] extends object - ? RamCostTree - : never; + [Property in keyof API]: API[Property] extends Function ? number | (() => number) : RamCostTree; }; -// TODO remember to update RamCalculations.js and WorkerScript.js - -// RAM costs for Netscript functions +/** Constants for assigning costs to ns functions */ export const RamCostConstants: Record = { ScriptBaseRamCost: 1.6, ScriptDomRamCost: 25, @@ -120,7 +113,7 @@ const hacknet = { getHashUpgradeLevel: 0, getStudyMult: 0, getTrainingMult: 0, -}; +} as const; // Stock API const stock = { @@ -149,7 +142,7 @@ const stock = { purchase4SMarketDataTixApi: RamCostConstants.ScriptBuySellStockRamCost, purchaseWseAccount: RamCostConstants.ScriptBuySellStockRamCost, purchaseTixApi: RamCostConstants.ScriptBuySellStockRamCost, -}; +} as const; // Singularity API const singularity = { @@ -208,7 +201,7 @@ const singularity = { b1tflum3: SF4Cost(16), destroyW0r1dD43m0n: SF4Cost(32), getCurrentWork: SF4Cost(0.5), -}; +} as const; // Gang API const gang = { @@ -233,7 +226,7 @@ const gang = { setTerritoryWarfare: RamCostConstants.ScriptGangApiBaseRamCost / 2, getChanceToWinClash: RamCostConstants.ScriptGangApiBaseRamCost, getBonusTime: 0, -}; +} as const; // Bladeburner API const bladeburner = { @@ -272,12 +265,12 @@ const bladeburner = { joinBladeburnerFaction: RamCostConstants.ScriptBladeburnerApiBaseRamCost, joinBladeburnerDivision: RamCostConstants.ScriptBladeburnerApiBaseRamCost, getBonusTime: 0, -}; +} as const; const infiltration = { getPossibleLocations: RamCostConstants.ScriptInfiltrationGetLocations, getInfiltration: RamCostConstants.ScriptInfiltrationGetInfiltrations, -}; +} as const; // Coding Contract API const codingcontract = { @@ -286,7 +279,7 @@ const codingcontract = { getData: RamCostConstants.ScriptCodingContractBaseRamCost / 2, getDescription: RamCostConstants.ScriptCodingContractBaseRamCost / 2, getNumTriesRemaining: RamCostConstants.ScriptCodingContractBaseRamCost / 5, -}; +} as const; // Duplicate Sleeve API const sleeve = { @@ -308,7 +301,7 @@ const sleeve = { setToBladeburnerAction: RamCostConstants.ScriptSleeveBaseRamCost, getSleeveAugmentationPrice: RamCostConstants.ScriptSleeveBaseRamCost, getSleeveAugmentationRepReq: RamCostConstants.ScriptSleeveBaseRamCost, -}; +} as const; // Stanek API const stanek = { @@ -323,7 +316,7 @@ const stanek = { getFragment: RamCostConstants.ScriptStanekFragmentAt, removeFragment: RamCostConstants.ScriptStanekDeleteAt, acceptGift: RamCostConstants.ScriptStanekAcceptGift, -}; +} as const; // UI API const ui = { @@ -336,7 +329,7 @@ const ui = { getGameInfo: 0, clearTerminal: 0, windowSize: 0, -}; +} as const; // Grafting API const grafting = { @@ -344,7 +337,7 @@ const grafting = { getAugmentationGraftTime: 3.75, getGraftableAugmentations: 5, graftAugmentation: 7.5, -}; +} as const; const corporation = { getMaterialNames: 0, @@ -412,16 +405,17 @@ const corporation = { hasResearched: 0, setAutoJobAssignment: 0, getOfficeSizeUpgradeCost: 0, -}; +} as const; -const SourceRamCosts = { - args: undefined as unknown as never[], // special use case - enums: undefined as unknown as never, +/** RamCosts guaranteed to match ns structure 1:1 (aside from args and enums). + * An error will be generated if there are missing OR additional ram costs defined. + * To avoid errors, define every function in NetscriptDefinition.d.ts and NetscriptFunctions, + * and have a ram cost associated here. */ +export const RamCosts: RamCostTree> = { corporation, hacknet, stock, singularity, - ...singularity, // singularity is in namespace & toplevel gang, bladeburner, infiltration, @@ -601,13 +595,7 @@ const SourceRamCosts = { factionGains: 0, }, }, -}; - -export const RamCosts: Record = SourceRamCosts; - -// This line in particular is there so typescript typechecks that we are not missing any static ram cost. -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const _typecheck: RamCostTree = SourceRamCosts; +} as const; export function getRamCost(...args: string[]): number { if (args.length === 0) { @@ -615,7 +603,7 @@ export function getRamCost(...args: string[]): number { return 0; } - let curr = RamCosts[args[0]]; + let curr = RamCosts[args[0] as keyof typeof RamCosts]; for (let i = 1; i < args.length; ++i) { if (curr == null) { console.warn(`Invalid function passed to getRamCost: ${args}`); @@ -627,7 +615,7 @@ export function getRamCost(...args: string[]): number { break; } - curr = curr[args[i]]; + curr = curr[args[i] as keyof typeof curr]; } if (typeof curr === "number") { diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index da7bf0f45..a163fca9f 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -4408,54 +4408,55 @@ export interface NS { * @remarks RAM cost: 4 GB */ readonly hacknet: Hacknet; + /** - * * Namespace for bladeburner functions. * @remarks RAM cost: 0 GB */ readonly bladeburner: Bladeburner; + /** - * * Namespace for codingcontract functions. * @remarks RAM cost: 0 GB */ readonly codingcontract: CodingContract; + /** - * * Namespace for gang functions. * @remarks RAM cost: 0 GB */ readonly gang: Gang; + /** - * * Namespace for sleeve functions. * @remarks RAM cost: 0 GB */ readonly sleeve: Sleeve; + /** - * * Namespace for stock functions. - * @remarks - * RAM cost: 0 GB + * @remarks RAM cost: 0 GB */ readonly stock: TIX; + /** - * * Namespace for formulas functions. - * @remarks - * RAM cost: 0 GB + * @remarks RAM cost: 0 GB */ readonly formulas: Formulas; + /** * Namespace for stanek functions. * RAM cost: 0 GB */ readonly stanek: Stanek; + /** * Namespace for infiltration functions. * RAM cost: 0 GB */ readonly infiltration: Infiltration; + /** * Namespace for corporation functions. * RAM cost: 1022.4 GB @@ -4476,8 +4477,7 @@ export interface NS { /** * Namespace for grafting functions. - * @remarks - * RAM cost: 0 GB + * @remarks RAM cost: 0 GB */ readonly grafting: Grafting; diff --git a/test/jest/Netscript/RamCalculation.test.ts b/test/jest/Netscript/RamCalculation.test.ts index 47672676d..569abec7b 100644 --- a/test/jest/Netscript/RamCalculation.test.ts +++ b/test/jest/Netscript/RamCalculation.test.ts @@ -42,20 +42,7 @@ describe("Netscript RAM Calculation/Generation Tests", function () { }; const ns = NetscriptFunctions(workerScript as WorkerScript); - /** - * Tests that: - * 1. A function has non-zero RAM cost, or zero if it is flagged as zero cost. - * 2. Running the function properly updates the MockWorkerScript's dynamic RAM calculation - * 3. Running multiple calls of the function does not result in additional RAM cost - * @param {string[]} fnDesc - describes the name of the function being tested, - * including the namespace(s). e.g. ["gang", "getMemberNames"] - */ - function testDynamicRamCost(fnDesc: string[], zero: boolean = false) { - const expected = getRamCost(...fnDesc); - zero ? expect(expected).toEqual(0) : expect(expected).toBeGreaterThan(0); - } - - function dynamicCheck(fnPath: string[], expectedRamCost: number) { + function dynamicCheck(fnPath: string[], expectedRamCost: number, extraLayerCost = 0) { const code = `${fnPath.join(".")}();\n`.repeat(3); const fnName = fnPath[fnPath.length - 1]; @@ -82,10 +69,10 @@ describe("Netscript RAM Calculation/Generation Tests", function () { expect(workerScript.dynamicLoadedFns).toHaveProperty(fnName); expect(workerScript.dynamicRamUsage - ScriptBaseCost).toBeCloseTo(expectedRamCost, 5); - expect(workerScript.dynamicRamUsage).toBeCloseTo(runningScript.ramUsage, 5); + expect(workerScript.dynamicRamUsage).toBeCloseTo(runningScript.ramUsage - extraLayerCost, 5); } - function testFunctionExpectZero(fnPath: string[]) { + function testFunctionExpectZero(fnPath: string[], extraLayerCost = 0) { const wholeFn = `${fnPath.join(".")}()`; describe(wholeFn, () => { it("Zero Ram Static Check", () => { @@ -93,13 +80,13 @@ describe("Netscript RAM Calculation/Generation Tests", function () { expect(ramCost).toEqual(0); const code = wholeFn; const staticCost = calculateRamUsage(code, []).cost; - expect(staticCost).toEqual(ScriptBaseCost); + expect(staticCost).toEqual(ScriptBaseCost + extraLayerCost); }); - it("Zero Ram Dynamic check", () => dynamicCheck(fnPath, 0)); + it("Zero Ram Dynamic check", () => dynamicCheck(fnPath, 0, extraLayerCost)); }); } - function testFunctionExpectNonzero(fnPath: string[]) { + function testFunctionExpectNonzero(fnPath: string[], extraLayerCost = 0) { const wholeFn = `${fnPath.join(".")}()`; const ramCost = getRamCost(...fnPath); describe(wholeFn, () => { @@ -107,13 +94,15 @@ describe("Netscript RAM Calculation/Generation Tests", function () { expect(ramCost).toBeGreaterThan(0); const code = wholeFn; const staticCost = calculateRamUsage(code, []).cost; - expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost, 5); + expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost + extraLayerCost, 5); }); - it("Dynamic Check", () => dynamicCheck(fnPath, ramCost)); + it("Dynamic Check", () => dynamicCheck(fnPath, ramCost, extraLayerCost)); }); } + //input type for testSingularityFunctions type singularityData = { fnPath: string[]; baseCost: number }; + function testSingularityFunctions(data: singularityData[]) { const sf4 = Player.sourceFiles[0]; data.forEach(({ fnPath, baseCost }) => { @@ -154,64 +143,89 @@ describe("Netscript RAM Calculation/Generation Tests", function () { [key: string]: NSLayer | unknown[] | (() => unknown); }; type RamLayer = { - [key: string]: number | (() => number); + [key: string]: RamLayer | number | (() => number); }; - function testLayer(nsLayer: NSLayer, ramLayer: RamLayer, path: string[]) { + function testLayer(nsLayer: NSLayer, ramLayer: RamLayer, path: string[], extraLayerCost = 0) { const zeroCostFunctions = Object.entries(nsLayer) .filter(([key, val]) => ramLayer[key] === 0 && typeof val === "function") .map(([key]) => [...path, key]); - zeroCostFunctions.forEach(testFunctionExpectZero); + zeroCostFunctions.forEach((fn) => testFunctionExpectZero(fn, extraLayerCost)); const nonzeroCostFunctions = Object.entries(nsLayer) .filter(([key, val]) => ramLayer[key] > 0 && typeof val === "function") .map(([key]) => [...path, key]); - nonzeroCostFunctions.forEach(testFunctionExpectNonzero); + nonzeroCostFunctions.forEach((fn) => testFunctionExpectNonzero(fn, extraLayerCost)); } - describe("Top level ns functions", function () { + describe("Top level ns functions", () => { const nsScope = ns as unknown as NSLayer; - const ramScope = RamCosts as unknown as RamLayer; + const ramScope = RamCosts; testLayer(nsScope, ramScope, []); }); - describe("TIX API (stock) functions", function () { - const nsScope = ns.stock as unknown as NSLayer; - const ramScope = RamCosts.stock as unknown as RamLayer; - testLayer(nsScope, ramScope, ["stock"]); - }); - - describe("Bladeburner API (bladeburner) functions", function () { + describe("Bladeburner API (bladeburner) functions", () => { const nsScope = ns.bladeburner as unknown as NSLayer; - const ramScope = RamCosts.bladeburner as unknown as RamLayer; + const ramScope = RamCosts.bladeburner; testLayer(nsScope, ramScope, ["bladeburner"]); }); - describe("Gang API (gang) functions", function () { + describe("Corporation API (corporation) functions", () => { + const nsScope = ns.corporation as unknown as NSLayer; + const ramScope = RamCosts.corporation; + testLayer(nsScope, ramScope, ["corporation"], 1024 - ScriptBaseCost); + }); + + describe("TIX API (stock) functions", () => { + const nsScope = ns.stock as unknown as NSLayer; + const ramScope = RamCosts.stock; + testLayer(nsScope, ramScope, ["stock"]); + }); + + describe("Gang API (gang) functions", () => { const nsScope = ns.gang as unknown as NSLayer; - const ramScope = RamCosts.gang as unknown as RamLayer; + const ramScope = RamCosts.gang; testLayer(nsScope, ramScope, ["gang"]); }); - describe("Coding Contract API (codingcontract) functions", function () { + describe("Coding Contract API (codingcontract) functions", () => { const nsScope = ns.codingcontract as unknown as NSLayer; - const ramScope = RamCosts.codingcontract as unknown as RamLayer; + const ramScope = RamCosts.codingcontract; testLayer(nsScope, ramScope, ["codingcontract"]); }); - describe("Sleeve API (sleeve) functions", function () { + describe("Sleeve API (sleeve) functions", () => { const nsScope = ns.sleeve as unknown as NSLayer; - const ramScope = RamCosts.sleeve as unknown as RamLayer; + const ramScope = RamCosts.sleeve; testLayer(nsScope, ramScope, ["sleeve"]); }); //Singularity functions are tested in a different way because they also check SF4 level effect - describe("ns.singularity functions", function () { - const singularityFunctions = Object.entries(RamCosts.singularity).map(([key, val]) => { + describe("ns.singularity functions", () => { + const singularityFunctions = Object.entries(RamCosts.singularity).map(([fnName, ramFn]) => { return { - fnPath: ["singularity", key], - baseCost: (val as () => number)(), + fnPath: ["singularity", fnName], + // This will error if a singularity function is assigned a flat cost instead of using the SF4 function + baseCost: (ramFn as () => number)(), }; }); testSingularityFunctions(singularityFunctions); }); + + //Formulas requires deeper layer penetration + function formulasTest( + newLayer = "formulas", + oldNSLayer = ns as unknown as NSLayer, + oldRamLayer = RamCosts as unknown as RamLayer, + path = ["formulas"], + nsLayer = oldNSLayer[newLayer] as NSLayer, + ramLayer = oldRamLayer[newLayer] as RamLayer, + ) { + testLayer(nsLayer, ramLayer, path); + for (const [key, val] of Object.entries(nsLayer)) { + if (Array.isArray(val) || typeof val === "function" || key === "enums") continue; + // Only other option is an object / new layer + describe(key, () => formulasTest(key, nsLayer, ramLayer, [...path, key])); + } + } + describe("ns.formulas functions", formulasTest); }); From a78a84c5b5cdd4e5ab2e6a5a0505b5ec59f9b45c Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Wed, 5 Oct 2022 13:14:24 -0400 Subject: [PATCH 6/8] Make ram checks more robust * Instead of hardcoded categories, automatically walk through all layers of ns, check for their associated costs, and check that ingame static and dynamic costs match the expected assigned costs. --- test/jest/Netscript/RamCalculation.test.ts | 244 +++++++-------------- 1 file changed, 81 insertions(+), 163 deletions(-) diff --git a/test/jest/Netscript/RamCalculation.test.ts b/test/jest/Netscript/RamCalculation.test.ts index 569abec7b..c29a10cde 100644 --- a/test/jest/Netscript/RamCalculation.test.ts +++ b/test/jest/Netscript/RamCalculation.test.ts @@ -7,8 +7,23 @@ import { Script } from "../../../src/Script/Script"; import { WorkerScript } from "../../../src/Netscript/WorkerScript"; import { calculateRamUsage } from "../../../src/Script/RamCalculations"; +type PotentiallyAsyncFunction = (arg?: unknown) => { catch?: PotentiallyAsyncFunction }; +type NSLayer = { + [key: string]: NSLayer | PotentiallyAsyncFunction; +}; +type RamLayer = { + [key: string]: number | (() => number) | RamLayer; +}; +function grabCost(ramLayer: RamLayer, fullPath: string[]) { + const ramEntry = ramLayer[fullPath[fullPath.length - 1]]; + const expectedRam = typeof ramEntry === "function" ? ramEntry() : ramEntry; + if (typeof expectedRam !== "number") throw new Error(`There was no defined ram cost for ${fullPath.join(".")}().`); + return expectedRam; +} + describe("Netscript RAM Calculation/Generation Tests", function () { Player.sourceFiles[0] = { n: 4, lvl: 3 }; + const sf4 = Player.sourceFiles[0]; // For simulating costs of singularity functions. const ScriptBaseCost = RamCostConstants.ScriptBaseRamCost; const script = new Script(); @@ -20,15 +35,14 @@ describe("Netscript RAM Calculation/Generation Tests", function () { return runningScript; } - type potentiallyAsyncFunction = (arg?: unknown) => { catch?: potentiallyAsyncFunction }; /** Runs a Netscript function and properly catches an error even if it returns promise. */ - function tryFunction(fn: potentiallyAsyncFunction) { + function tryFunction(fn: PotentiallyAsyncFunction) { try { fn()?.catch?.(() => undefined); } catch {} } - let runningScript = createRunningScript(""); + let scriptRef = createRunningScript(""); //Since it is expensive to create a workerscript and wrap the ns API, this is done once const workerScript = { args: [] as string[], @@ -37,28 +51,40 @@ describe("Netscript RAM Calculation/Generation Tests", function () { dynamicLoadedFns: {}, dynamicRamUsage: RamCostConstants.ScriptBaseRamCost, env: new Environment(), - ramUsage: runningScript.ramUsage, - scriptRef: runningScript, + ramUsage: scriptRef.ramUsage, + scriptRef, }; const ns = NetscriptFunctions(workerScript as WorkerScript); - function dynamicCheck(fnPath: string[], expectedRamCost: number, extraLayerCost = 0) { + function combinedRamCheck( + fn: PotentiallyAsyncFunction, + fnPath: string[], + expectedRamCost: number, + extraLayerCost = 0, + ) { const code = `${fnPath.join(".")}();\n`.repeat(3); const fnName = fnPath[fnPath.length - 1]; - // update our existing WorkerScript - runningScript = createRunningScript(code); - workerScript.code = code; - workerScript.scriptRef = runningScript; - workerScript.ramUsage = workerScript.scriptRef.ramUsage; - workerScript.dynamicRamUsage = ScriptBaseCost; - workerScript.env = new Environment(); - workerScript.dynamicLoadedFns = {}; + //check imported getRamCost fn vs. expected ram from test + expect(getRamCost(...fnPath)).toEqual(expectedRamCost); + + // Static ram check + const staticCost = calculateRamUsage(code, []).cost; + expect(staticCost).toBeCloseTo(ScriptBaseCost + expectedRamCost + extraLayerCost); + + // reset workerScript for dynamic check + scriptRef = createRunningScript(code); + Object.assign(workerScript, { + code, + scriptRef, + ramUsage: scriptRef.ramUsage, + dynamicRamUsage: ScriptBaseCost, + env: new Environment(), + dynamicLoadedFns: {}, + }); workerScript.env.vars = ns; // Run the function through the workerscript's args - const fn = fnPath.reduce((prev, curr) => prev[curr], ns as any); - if (typeof fn === "function") { tryFunction(fn); tryFunction(fn); @@ -69,163 +95,55 @@ describe("Netscript RAM Calculation/Generation Tests", function () { expect(workerScript.dynamicLoadedFns).toHaveProperty(fnName); expect(workerScript.dynamicRamUsage - ScriptBaseCost).toBeCloseTo(expectedRamCost, 5); - expect(workerScript.dynamicRamUsage).toBeCloseTo(runningScript.ramUsage - extraLayerCost, 5); + expect(workerScript.dynamicRamUsage).toBeCloseTo(scriptRef.ramUsage - extraLayerCost, 5); } - function testFunctionExpectZero(fnPath: string[], extraLayerCost = 0) { - const wholeFn = `${fnPath.join(".")}()`; - describe(wholeFn, () => { - it("Zero Ram Static Check", () => { - const ramCost = getRamCost(...fnPath); - expect(ramCost).toEqual(0); - const code = wholeFn; - const staticCost = calculateRamUsage(code, []).cost; - expect(staticCost).toEqual(ScriptBaseCost + extraLayerCost); - }); - it("Zero Ram Dynamic check", () => dynamicCheck(fnPath, 0, extraLayerCost)); + describe("ns", () => { + Object.entries(ns as unknown as NSLayer).forEach(([key, val]) => { + if (key === "args" || key === "enums") return; + if (typeof val === "function") { + const expectedRam = grabCost(RamCosts, [key]); + it(`${key}()`, () => combinedRamCheck(val, [key], expectedRam)); + } + //The only other option should be an NSLayer + const extraLayerCost = { corporation: 1022.4, hacknet: 4 }[key] ?? 0; + testLayer(val as NSLayer, RamCosts[key as keyof typeof RamCosts] as RamLayer, [key], extraLayerCost); }); - } + }); - function testFunctionExpectNonzero(fnPath: string[], extraLayerCost = 0) { - const wholeFn = `${fnPath.join(".")}()`; - const ramCost = getRamCost(...fnPath); - describe(wholeFn, () => { - it("Static Check", () => { - expect(ramCost).toBeGreaterThan(0); - const code = wholeFn; - const staticCost = calculateRamUsage(code, []).cost; - expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost + extraLayerCost, 5); - }); - it("Dynamic Check", () => dynamicCheck(fnPath, ramCost, extraLayerCost)); - }); - } - - //input type for testSingularityFunctions - type singularityData = { fnPath: string[]; baseCost: number }; - - function testSingularityFunctions(data: singularityData[]) { - const sf4 = Player.sourceFiles[0]; - data.forEach(({ fnPath, baseCost }) => { - const wholeFn = `${fnPath.join(".")}()`; - describe(wholeFn, () => { - it("SF4.3", () => { - sf4.lvl = 3; - const ramCost = getRamCost(...fnPath); - expect(ramCost).toEqual(baseCost); - const code = wholeFn; - const staticCost = calculateRamUsage(code, []).cost; - expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost); - dynamicCheck(fnPath, baseCost); - }); - it("SF4.2", () => { - sf4.lvl = 2; - const ramCost = getRamCost(...fnPath); - expect(ramCost).toBeCloseTo(baseCost * 4, 5); - const code = wholeFn; - const staticCost = calculateRamUsage(code, []).cost; - expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost); - dynamicCheck(fnPath, ramCost); - }); - it("SF4.1", () => { - sf4.lvl = 1; - const ramCost = getRamCost(...fnPath); - expect(ramCost).toBeCloseTo(baseCost * 16, 5); - const code = wholeFn; - const staticCost = calculateRamUsage(code, []).cost; - expect(staticCost).toBeCloseTo(ramCost + ScriptBaseCost); - dynamicCheck(fnPath, ramCost); - }); + function testLayer(nsLayer: NSLayer, ramLayer: RamLayer, path: string[], extraLayerCost: number) { + describe(path[path.length - 1], () => { + Object.entries(nsLayer).forEach(([key, val]) => { + const newPath = [...path, key]; + if (typeof val === "function") { + const fnName = newPath.join("."); + const expectedRam = grabCost(ramLayer, newPath); + it(`${fnName}()`, () => combinedRamCheck(val, newPath, expectedRam, extraLayerCost)); + } + //A layer should be the only other option. + else testLayer(val, ramLayer[key] as RamLayer, newPath, 0); }); }); } - type NSLayer = { - [key: string]: NSLayer | unknown[] | (() => unknown); - }; - type RamLayer = { - [key: string]: RamLayer | number | (() => number); - }; - function testLayer(nsLayer: NSLayer, ramLayer: RamLayer, path: string[], extraLayerCost = 0) { - const zeroCostFunctions = Object.entries(nsLayer) - .filter(([key, val]) => ramLayer[key] === 0 && typeof val === "function") - .map(([key]) => [...path, key]); - zeroCostFunctions.forEach((fn) => testFunctionExpectZero(fn, extraLayerCost)); - - const nonzeroCostFunctions = Object.entries(nsLayer) - .filter(([key, val]) => ramLayer[key] > 0 && typeof val === "function") - .map(([key]) => [...path, key]); - nonzeroCostFunctions.forEach((fn) => testFunctionExpectNonzero(fn, extraLayerCost)); - } - - describe("Top level ns functions", () => { - const nsScope = ns as unknown as NSLayer; - const ramScope = RamCosts; - testLayer(nsScope, ramScope, []); - }); - - describe("Bladeburner API (bladeburner) functions", () => { - const nsScope = ns.bladeburner as unknown as NSLayer; - const ramScope = RamCosts.bladeburner; - testLayer(nsScope, ramScope, ["bladeburner"]); - }); - - describe("Corporation API (corporation) functions", () => { - const nsScope = ns.corporation as unknown as NSLayer; - const ramScope = RamCosts.corporation; - testLayer(nsScope, ramScope, ["corporation"], 1024 - ScriptBaseCost); - }); - - describe("TIX API (stock) functions", () => { - const nsScope = ns.stock as unknown as NSLayer; - const ramScope = RamCosts.stock; - testLayer(nsScope, ramScope, ["stock"]); - }); - - describe("Gang API (gang) functions", () => { - const nsScope = ns.gang as unknown as NSLayer; - const ramScope = RamCosts.gang; - testLayer(nsScope, ramScope, ["gang"]); - }); - - describe("Coding Contract API (codingcontract) functions", () => { - const nsScope = ns.codingcontract as unknown as NSLayer; - const ramScope = RamCosts.codingcontract; - testLayer(nsScope, ramScope, ["codingcontract"]); - }); - - describe("Sleeve API (sleeve) functions", () => { - const nsScope = ns.sleeve as unknown as NSLayer; - const ramScope = RamCosts.sleeve; - testLayer(nsScope, ramScope, ["sleeve"]); - }); - - //Singularity functions are tested in a different way because they also check SF4 level effect - describe("ns.singularity functions", () => { - const singularityFunctions = Object.entries(RamCosts.singularity).map(([fnName, ramFn]) => { + describe("Singularity multiplier checks", () => { + sf4.lvl = 3; + const singFunctions = Object.entries(ns.singularity).filter(([key, val]) => typeof val === "function"); + const singObjects = singFunctions.map(([key, val]) => { return { - fnPath: ["singularity", fnName], - // This will error if a singularity function is assigned a flat cost instead of using the SF4 function - baseCost: (ramFn as () => number)(), + name: key, + fn: val, + baseRam: grabCost(RamCosts.singularity, ["singularity", key]), }; }); - testSingularityFunctions(singularityFunctions); - }); - - //Formulas requires deeper layer penetration - function formulasTest( - newLayer = "formulas", - oldNSLayer = ns as unknown as NSLayer, - oldRamLayer = RamCosts as unknown as RamLayer, - path = ["formulas"], - nsLayer = oldNSLayer[newLayer] as NSLayer, - ramLayer = oldRamLayer[newLayer] as RamLayer, - ) { - testLayer(nsLayer, ramLayer, path); - for (const [key, val] of Object.entries(nsLayer)) { - if (Array.isArray(val) || typeof val === "function" || key === "enums") continue; - // Only other option is an object / new layer - describe(key, () => formulasTest(key, nsLayer, ramLayer, [...path, key])); + const lvlToMult: Record = { 0: 16, 1: 16, 2: 4 }; + for (const lvl of [0, 1, 2]) { + it(`SF4.${lvl} check for x${lvlToMult[lvl]} costs`, () => { + sf4.lvl = lvl; + singObjects.forEach((obj) => + combinedRamCheck(obj.fn, ["singularity", obj.name], obj.baseRam * lvlToMult[lvl], 0), + ); + }); } - } - describe("ns.formulas functions", formulasTest); + }); }); From 068533cd2f02903beb4a2a9aaf0580bb7c6e64df Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Wed, 5 Oct 2022 14:52:48 -0400 Subject: [PATCH 7/8] format, lint, more enums, revert fn rename --- src/BitNode/BitNodeMultipliers.ts | 18 ++++---- src/CodingContractGenerator.ts | 2 +- src/Corporation/Actions.ts | 6 +-- src/Corporation/EmployeePositions.ts | 18 ++++---- src/Corporation/Industry.ts | 4 +- src/Literature/data/LiteratureNames.ts | 46 +++++++++---------- src/Netscript/RamCostGenerator.ts | 2 +- src/NetscriptFunctions.ts | 12 ++--- src/NetscriptFunctions/Corporation.ts | 6 +-- src/NetscriptFunctions/Infiltration.ts | 4 +- src/NetscriptFunctions/Sleeve.ts | 4 +- src/RedPill.tsx | 2 +- src/SaveObject.tsx | 2 +- src/ScriptEditor/NetscriptDefinitions.d.ts | 17 ++++--- src/Settings/Settings.ts | 8 ++-- src/StockMarket/StockMarket.tsx | 15 +++--- src/StockMarket/data/StockSymbols.ts | 1 + .../data/TickerHeaderFormatData.ts | 4 +- src/Terminal/commands/cat.ts | 4 +- src/engine.tsx | 3 +- src/ui/React/Snackbar.tsx | 6 +-- src/utils/helpers/checkEnum.ts | 4 ++ src/utils/helpers/checkObjContains.ts | 7 --- 23 files changed, 94 insertions(+), 101 deletions(-) create mode 100644 src/utils/helpers/checkEnum.ts delete mode 100644 src/utils/helpers/checkObjContains.ts diff --git a/src/BitNode/BitNodeMultipliers.ts b/src/BitNode/BitNodeMultipliers.ts index a773f106e..fbe078db9 100644 --- a/src/BitNode/BitNodeMultipliers.ts +++ b/src/BitNode/BitNodeMultipliers.ts @@ -86,34 +86,34 @@ export interface IBitNodeMultipliers { * Influeces the hash rate of Hacknet Servers (unlocked in BitNode-9) */ HacknetNodeMoney: number; - + /** Influences how much money it costs to upgrade your home computer's RAM */ HomeComputerRamCost: number; - + /** Influences how much money is gained when the player infiltrates a company. */ InfiltrationMoney: number; - + /** Influences how much rep the player can gain from factions when selling stolen documents and secrets */ InfiltrationRep: number; - + /** * Influences how much money can be stolen from a server when the player performs a hack against it through * the Terminal. */ ManualHackMoney: number; - + /** Influence how much it costs to purchase a server */ PurchasedServerCost: number; - + /** Influence how much it costs to purchase a server */ PurchasedServerSoftcap: number; - + /** Influences the maximum number of purchased servers you can have */ PurchasedServerLimit: number; - + /** Influences the maximum allowed RAM for a purchased server */ PurchasedServerMaxRam: number; - + /** Influences the minimum favor the player must have with a faction before they can donate to gain rep. */ RepToDonateToFaction: number; diff --git a/src/CodingContractGenerator.ts b/src/CodingContractGenerator.ts index 9f913ed48..32328c59e 100644 --- a/src/CodingContractGenerator.ts +++ b/src/CodingContractGenerator.ts @@ -55,7 +55,7 @@ export function generateContract(params: IGenerateContractParams): void { // Problem Type let problemType; const problemTypes = Object.keys(CodingContractTypes); - if (params.problemType != null && problemTypes.includes(params.problemType)) { + if (params.problemType && problemTypes.includes(params.problemType)) { problemType = params.problemType; } else { problemType = getRandomProblemType(); diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index 5cdfc5e9f..f8f4ab748 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -14,7 +14,7 @@ import { Cities } from "../Locations/Cities"; import { EmployeePositions } from "./EmployeePositions"; import { ResearchMap } from "./ResearchMap"; import { isRelevantMaterial } from "./ui/Helpers"; -import { checkObjContainsValue } from "../utils/helpers/checkObjContains"; +import { checkEnum } from "../utils/helpers/checkEnum"; export function NewIndustry(corporation: Corporation, industry: string, name: string): void { if (corporation.divisions.find(({ type }) => industry == type)) @@ -305,12 +305,12 @@ export function BuyBackShares(corporation: Corporation, numShares: number): bool export function AssignJob(office: OfficeSpace, employeeName: string, job: string): void { const employee = office.employees.find((e) => e.name === employeeName); if (!employee) throw new Error(`Could not find employee '${name}'.`); - if (!checkObjContainsValue(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`) + if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); office.assignSingleJob(employee, job); } export function AutoAssignJob(office: OfficeSpace, job: string, count: number): boolean { - if (!checkObjContainsValue(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`) + if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); return office.autoAssignJob(job, count); } diff --git a/src/Corporation/EmployeePositions.ts b/src/Corporation/EmployeePositions.ts index e560314c6..c33eae207 100644 --- a/src/Corporation/EmployeePositions.ts +++ b/src/Corporation/EmployeePositions.ts @@ -1,9 +1,9 @@ -export const EmployeePositions = { - Operations: "Operations", - Engineer: "Engineer", - Business: "Business", - Management: "Management", - RandD: "Research & Development", - Training: "Training", - Unassigned: "Unassigned", -} as const; +export enum EmployeePositions { + Operations = "Operations", + Engineer = "Engineer", + Business = "Business", + Management = "Management", + RandD = "Research & Development", + Training = "Training", + Unassigned = "Unassigned", +} diff --git a/src/Corporation/Industry.ts b/src/Corporation/Industry.ts index dd2c75a0f..532b56949 100644 --- a/src/Corporation/Industry.ts +++ b/src/Corporation/Industry.ts @@ -602,6 +602,7 @@ export class Industry { } } + // TODO: Change all these Object.keys where the value is also needed to Object.entries. // Use the materials already in the warehouse if the option is on. for (const matName of Object.keys(smartBuy)) { if (!warehouse.smartSupplyUseLeftovers[matName]) continue; @@ -612,9 +613,8 @@ export class Industry { } // buy them - for (const matName of Object.keys(smartBuy)) { + for (const [matName, buyAmt] of Object.entries(smartBuy)) { const mat = warehouse.materials[matName]; - const buyAmt = smartBuy[matName]; if (buyAmt === undefined) throw new Error(`Somehow smartbuy matname is undefined`); mat.qty += buyAmt; expenses += buyAmt * mat.bCost; diff --git a/src/Literature/data/LiteratureNames.ts b/src/Literature/data/LiteratureNames.ts index 712134bd5..fb005f403 100644 --- a/src/Literature/data/LiteratureNames.ts +++ b/src/Literature/data/LiteratureNames.ts @@ -1,23 +1,23 @@ -export const LiteratureNames = { - HackersStartingHandbook: "hackers-starting-handbook.lit", - CorporationManagementHandbook: "corporation-management-handbook.lit", - HistoryOfSynthoids: "history-of-synthoids.lit", - AGreenTomorrow: "A-Green-Tomorrow.lit", - AlphaOmega: "alpha-omega.lit", - SimulatedReality: "simulated-reality.lit", - BeyondMan: "beyond-man.lit", - BrighterThanTheSun: "brighter-than-the-sun.lit", - DemocracyIsDead: "democracy-is-dead.lit", - Sector12Crime: "sector-12-crime.lit", - ManAndMachine: "man-and-machine.lit", - SecretSocieties: "secret-societies.lit", - TheFailedFrontier: "the-failed-frontier.lit", - CodedIntelligence: "coded-intelligence.lit", - SyntheticMuscles: "synthetic-muscles.lit", - TensionsInTechRace: "tensions-in-tech-race.lit", - CostOfImmortality: "cost-of-immortality.lit", - TheHiddenWorld: "the-hidden-world.lit", - TheNewGod: "the-new-god.lit", - NewTriads: "new-triads.lit", - TheSecretWar: "the-secret-war.lit", -} as const; +export enum LiteratureNames { + HackersStartingHandbook = "hackers-starting-handbook.lit", + CorporationManagementHandbook = "corporation-management-handbook.lit", + HistoryOfSynthoids = "history-of-synthoids.lit", + AGreenTomorrow = "A-Green-Tomorrow.lit", + AlphaOmega = "alpha-omega.lit", + SimulatedReality = "simulated-reality.lit", + BeyondMan = "beyond-man.lit", + BrighterThanTheSun = "brighter-than-the-sun.lit", + DemocracyIsDead = "democracy-is-dead.lit", + Sector12Crime = "sector-12-crime.lit", + ManAndMachine = "man-and-machine.lit", + SecretSocieties = "secret-societies.lit", + TheFailedFrontier = "the-failed-frontier.lit", + CodedIntelligence = "coded-intelligence.lit", + SyntheticMuscles = "synthetic-muscles.lit", + TensionsInTechRace = "tensions-in-tech-race.lit", + CostOfImmortality = "cost-of-immortality.lit", + TheHiddenWorld = "the-hidden-world.lit", + TheNewGod = "the-new-god.lit", + NewTriads = "new-triads.lit", + TheSecretWar = "the-secret-war.lit", +} diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index 2a8fa9dd7..8f140aea5 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -3,7 +3,7 @@ import { NSFull } from "../NetscriptFunctions"; /** This type assumes any value that isn't an API layer or a function has been omitted (args and enum) */ type RamCostTree = { - [Property in keyof API]: API[Property] extends Function ? number | (() => number) : RamCostTree; + [Property in keyof API]: API[Property] extends () => unknown ? number | (() => number) : RamCostTree; }; /** Constants for assigning costs to ns functions */ diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 816abad79..0ef50f7a6 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -71,7 +71,7 @@ import { NetscriptSingularity } from "./NetscriptFunctions/Singularity"; import { dialogBoxCreate } from "./ui/React/DialogBox"; import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; -import { checkObjContainsValue } from "./utils/helpers/checkObjContains"; +import { checkEnum } from "./utils/helpers/checkEnum"; import { Flags } from "./NetscriptFunctions/Flags"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; @@ -85,7 +85,7 @@ import { ScriptDeath } from "./Netscript/ScriptDeath"; export const enums = { toast: ToastVariant, } as const; -export type NSFull = NS & INetscriptExtra; +export type NSFull = Readonly; export function NetscriptFunctions(workerScript: WorkerScript): NSFull { return wrapAPI(workerScript, ns, workerScript.args.slice()); @@ -1784,12 +1784,12 @@ const base: InternalAPI = { }, toast: (ctx: NetscriptContext) => - (_message: unknown, _variant: unknown = enums.toast.SUCCESS, _duration: unknown = 2000): void => { + (_message: unknown, _variant: unknown = ToastVariant.SUCCESS, _duration: unknown = 2000): void => { const message = helpers.string(ctx, "message", _message); const variant = helpers.string(ctx, "variant", _variant); const duration = _duration === null ? null : helpers.number(ctx, "duration", _duration); - if (!checkObjContainsValue(enums.toast, variant)) - throw new Error(`variant must be one of ${Object.values(enums.toast).join(", ")}`); + if (!checkEnum(ToastVariant, variant)) + throw new Error(`variant must be one of ${Object.values(ToastVariant).join(", ")}`); SnackbarEvents.emit(message, variant as ToastVariant, duration); }, prompt: @@ -1947,7 +1947,7 @@ const base: InternalAPI = { }; // add undocumented functions -const ns = { +export const ns = { ...base, ...NetscriptExtra(), }; diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts index 23c82bf0e..996d956dc 100644 --- a/src/NetscriptFunctions/Corporation.ts +++ b/src/NetscriptFunctions/Corporation.ts @@ -66,7 +66,7 @@ import { Factions } from "../Faction/Factions"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { helpers } from "../Netscript/NetscriptHelpers"; -import { checkObjContainsValue } from "../utils/helpers/checkObjContains"; +import { checkEnum } from "../utils/helpers/checkEnum"; export function NetscriptCorporation(): InternalAPI { function createCorporation(corporationName: string, selfFund = true): boolean { @@ -712,7 +712,7 @@ export function NetscriptCorporation(): InternalAPI { const employeeName = helpers.string(ctx, "employeeName", _employeeName); const job = helpers.string(ctx, "job", _job); - if (!checkObjContainsValue(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); + if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); const office = getOffice(divisionName, cityName); AssignJob(office, employeeName, job); @@ -726,7 +726,7 @@ export function NetscriptCorporation(): InternalAPI { const amount = helpers.number(ctx, "amount", _amount); const job = helpers.string(ctx, "job", _job); - if (!checkObjContainsValue(EmployeePositions,job)) throw new Error(`'${job}' is not a valid job.`); + if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); const office = getOffice(divisionName, cityName); return AutoAssignJob(office, job, amount); diff --git a/src/NetscriptFunctions/Infiltration.ts b/src/NetscriptFunctions/Infiltration.ts index dd419a11c..620e5a4bf 100644 --- a/src/NetscriptFunctions/Infiltration.ts +++ b/src/NetscriptFunctions/Infiltration.ts @@ -14,7 +14,7 @@ import { import { FactionNames } from "../Faction/data/FactionNames"; import { Factions } from "../Faction/Factions"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; -import { checkObjContainsValue } from "../utils/helpers/checkObjContains"; +import { checkEnum } from "../utils/helpers/checkEnum"; import { LocationName } from "../Locations/data/LocationNames"; import { helpers } from "../Netscript/NetscriptHelpers"; @@ -24,7 +24,7 @@ export function NetscriptInfiltration(): InternalAPI { ); const calculateInfiltrationData = (ctx: NetscriptContext, locationName: string): InfiltrationLocation => { - if (!checkObjContainsValue(LocationName, locationName)) throw new Error(`Location '${locationName}' does not exists.`); + if (!checkEnum(LocationName, locationName)) throw new Error(`Location '${locationName}' does not exists.`); const location = Locations[locationName]; if (location === undefined) throw helpers.makeRuntimeErrorMsg(ctx, `Location '${location}' does not exists.`); if (location.infiltrationData === undefined) diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts index 1359b36d6..db24151dd 100644 --- a/src/NetscriptFunctions/Sleeve.ts +++ b/src/NetscriptFunctions/Sleeve.ts @@ -11,7 +11,7 @@ import { SleeveSkills, SleeveTask, } from "../ScriptEditor/NetscriptDefinitions"; -import { checkObjContainsValue } from "../utils/helpers/checkObjContains"; +import { checkEnum } from "../utils/helpers/checkEnum"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBladeburnerWork"; import { isSleeveFactionWork } from "../PersonObjects/Sleeve/Work/SleeveFactionWork"; @@ -102,7 +102,7 @@ export function NetscriptSleeve(): InternalAPI { const cityName = helpers.string(ctx, "cityName", _cityName); checkSleeveAPIAccess(ctx); checkSleeveNumber(ctx, sleeveNumber); - if (checkObjContainsValue(CityName, cityName)) { + if (checkEnum(CityName, cityName)) { return Player.sleeves[sleeveNumber].travel(cityName); } else { throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`); diff --git a/src/RedPill.tsx b/src/RedPill.tsx index a1b8ea13e..6f9722f21 100644 --- a/src/RedPill.tsx +++ b/src/RedPill.tsx @@ -17,7 +17,7 @@ function giveSourceFile(bitNodeNumber: number): void { } // Check if player already has this source file - const ownedSourceFile = Player.sourceFiles.find(sourceFile=>sourceFile.n === bitNodeNumber) + const ownedSourceFile = Player.sourceFiles.find((sourceFile) => sourceFile.n === bitNodeNumber); if (ownedSourceFile) { if (ownedSourceFile.lvl >= 3 && ownedSourceFile.n !== 12) { diff --git a/src/SaveObject.tsx b/src/SaveObject.tsx index 14120faa1..24ce4b266 100755 --- a/src/SaveObject.tsx +++ b/src/SaveObject.tsx @@ -707,7 +707,7 @@ function loadGame(saveString: string): boolean { } if (saveObj.hasOwnProperty("SettingsSave")) { try { - // Try to set saved settings. + // Try to set saved settings. Settings.load(saveObj.SettingsSave); } catch (e) {} } diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index a163fca9f..42cf517d3 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -4408,49 +4408,49 @@ export interface NS { * @remarks RAM cost: 4 GB */ readonly hacknet: Hacknet; - + /** * Namespace for bladeburner functions. * @remarks RAM cost: 0 GB */ readonly bladeburner: Bladeburner; - + /** * Namespace for codingcontract functions. * @remarks RAM cost: 0 GB */ readonly codingcontract: CodingContract; - + /** * Namespace for gang functions. * @remarks RAM cost: 0 GB */ readonly gang: Gang; - + /** * Namespace for sleeve functions. * @remarks RAM cost: 0 GB */ readonly sleeve: Sleeve; - + /** * Namespace for stock functions. * @remarks RAM cost: 0 GB */ readonly stock: TIX; - + /** * Namespace for formulas functions. * @remarks RAM cost: 0 GB */ readonly formulas: Formulas; - + /** * Namespace for stanek functions. * RAM cost: 0 GB */ readonly stanek: Stanek; - + /** * Namespace for infiltration functions. * RAM cost: 0 GB @@ -6533,7 +6533,6 @@ declare const enums = { } as const; type ToastVariant = ValuesFrom; - export type NSEnums = typeof enums; /** * Corporation Office API diff --git a/src/Settings/Settings.ts b/src/Settings/Settings.ts index 7846aad23..a2c87e41b 100644 --- a/src/Settings/Settings.ts +++ b/src/Settings/Settings.ts @@ -65,13 +65,13 @@ export const Settings = { /** Whether the game's sidebar is opened. */ IsSidebarOpened: true, /** Theme colors. */ - theme: {...defaultTheme}, + theme: { ...defaultTheme }, /** Interface styles. */ - styles: {...defaultStyles}, + styles: { ...defaultStyles }, /** Character overview settings. */ overview: { x: 0, y: 0, opened: true }, /** Script editor theme data. */ - EditorTheme: {...defaultMonacoTheme}, + EditorTheme: { ...defaultMonacoTheme }, /** Order to display the player's owned Augmentations/Source Files. */ OwnedAugmentationsOrder: OwnedAugmentationsOrderSetting.AcquirementTime, /** What order the Augmentations should be displayed in when purchasing from a Faction. */ @@ -85,7 +85,7 @@ export const Settings = { MonacoVim: false, /** Word wrap setting for Script Editor. */ MonacoWordWrap: "off" as WordWrapOptions, - + load(saveString: string) { const save = JSON.parse(saveString); save.theme && Object.assign(Settings.theme, save.theme); diff --git a/src/StockMarket/StockMarket.tsx b/src/StockMarket/StockMarket.tsx index dabc29afd..5728d78a2 100644 --- a/src/StockMarket/StockMarket.tsx +++ b/src/StockMarket/StockMarket.tsx @@ -170,16 +170,13 @@ export function initStockMarket(): void { } export function initSymbolToStockMap(): void { - for (const name of Object.keys(StockSymbols) as Array) { - if (StockSymbols.hasOwnProperty(name)) { - const stock = StockMarket[name]; - if (stock == null) { - console.error(`Could not find Stock for ${name}`); - continue; - } - const symbol = StockSymbols[name]; - SymbolToStockMap[symbol] = stock; + for (const [name, symbol] of Object.entries(StockSymbols)) { + const stock = StockMarket[name]; + if (stock == null) { + console.error(`Could not find Stock for ${name}`); + continue; } + SymbolToStockMap[symbol] = stock; } } diff --git a/src/StockMarket/data/StockSymbols.ts b/src/StockMarket/data/StockSymbols.ts index d41ddcf69..3be3a410a 100644 --- a/src/StockMarket/data/StockSymbols.ts +++ b/src/StockMarket/data/StockSymbols.ts @@ -1,5 +1,6 @@ import { LocationName } from "../../Locations/data/LocationNames"; +//Enum-like object because some keys are created via code and have spaces. Membership can still be checked with checkEnum. export const StockSymbols = { // Stocks for companies at which you can work [LocationName.AevumECorp]: "ECP", diff --git a/src/StockMarket/data/TickerHeaderFormatData.ts b/src/StockMarket/data/TickerHeaderFormatData.ts index 1ad7e8f49..bac070239 100644 --- a/src/StockMarket/data/TickerHeaderFormatData.ts +++ b/src/StockMarket/data/TickerHeaderFormatData.ts @@ -5,7 +5,7 @@ export const TickerHeaderFormatData = { longestSymbol: 0, }; -for (const key of Object.keys(StockSymbols) as Array) { +for (const [key, symbol] of Object.entries(StockSymbols)) { TickerHeaderFormatData.longestName = Math.max(key.length, TickerHeaderFormatData.longestName); - TickerHeaderFormatData.longestSymbol = Math.max(StockSymbols[key].length, TickerHeaderFormatData.longestSymbol); + TickerHeaderFormatData.longestSymbol = Math.max(symbol.length, TickerHeaderFormatData.longestSymbol); } diff --git a/src/Terminal/commands/cat.ts b/src/Terminal/commands/cat.ts index b8fcc9dd0..0807e8a84 100644 --- a/src/Terminal/commands/cat.ts +++ b/src/Terminal/commands/cat.ts @@ -3,7 +3,7 @@ import { BaseServer } from "../../Server/BaseServer"; import { MessageFilenames, showMessage } from "../../Message/MessageHelpers"; import { showLiterature } from "../../Literature/LiteratureHelpers"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; -import { checkObjContainsValue } from "../../utils/helpers/checkObjContains"; +import { checkEnum } from "../../utils/helpers/checkEnum"; export function cat(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 1) { @@ -35,7 +35,7 @@ export function cat(args: (string | number | boolean)[], server: BaseServer): vo } else if (filename.endsWith(".msg")) { const file = server.messages[i]; if (file !== filename) continue; - if (!checkObjContainsValue(MessageFilenames, file)) return; + if (!checkEnum(MessageFilenames, file)) return; showMessage(file); return; } diff --git a/src/engine.tsx b/src/engine.tsx index 880e66626..0d2c3ca00 100644 --- a/src/engine.tsx +++ b/src/engine.tsx @@ -145,8 +145,7 @@ const Engine: { }, decrementAllCounters: function (numCycles = 1) { - for (const counterName of Object.keys(Engine.Counters)) { - const counter = Engine.Counters[counterName]; + for (const [counterName, counter] of Object.entries(Engine.Counters)) { if (counter === undefined) throw new Error("counter should not be undefined"); Engine.Counters[counterName] = counter - numCycles; } diff --git a/src/ui/React/Snackbar.tsx b/src/ui/React/Snackbar.tsx index 0225418f3..1f3087a5a 100644 --- a/src/ui/React/Snackbar.tsx +++ b/src/ui/React/Snackbar.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from "react"; import { useSnackbar, SnackbarProvider as SB } from "notistack"; import makeStyles from "@mui/styles/makeStyles"; import { EventEmitter } from "../../utils/EventEmitter"; -import Alert, { AlertColor } from "@mui/material/Alert"; +import Alert from "@mui/material/Alert"; import Paper from "@mui/material/Paper"; import { logBoxBaseZIndex } from "./LogBoxManager"; @@ -10,12 +10,12 @@ interface IProps { children: React.ReactNode | React.ReactNode[]; } -export enum ToastVariant{ +export enum ToastVariant { SUCCESS = "success", WARNING = "warning", ERROR = "error", INFO = "info", -}; +} const useStyles = makeStyles(() => ({ snackbar: { diff --git a/src/utils/helpers/checkEnum.ts b/src/utils/helpers/checkEnum.ts new file mode 100644 index 000000000..b3eb24d48 --- /dev/null +++ b/src/utils/helpers/checkEnum.ts @@ -0,0 +1,4 @@ +// This works for both enums and regular objects. +export function checkEnum>(obj: T, value: unknown): value is T[keyof T] { + return Object.values(obj).includes(value); +} diff --git a/src/utils/helpers/checkObjContains.ts b/src/utils/helpers/checkObjContains.ts deleted file mode 100644 index a0df51d7a..000000000 --- a/src/utils/helpers/checkObjContains.ts +++ /dev/null @@ -1,7 +0,0 @@ -// This works for both enums and regular objects. -export function checkObjContainsValue>( - obj: T, - value: string, -): value is T[keyof T] { - return Object.values(obj).includes(value); -} From 0310a982372cccb89dbf0a5ba06c7b5e5d3fbfc0 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Wed, 5 Oct 2022 15:24:27 -0400 Subject: [PATCH 8/8] Lint+format fix? --- src/ScriptEditor/NetscriptDefinitions.d.ts | 9 ++++++--- test/jest/Netscript/RamCalculation.test.ts | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 42cf517d3..44f0b3233 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -215,7 +215,8 @@ export interface CrimeStats { * @public */ export interface BasicHGWOptions { - /** Number of threads to use for this function. Must be less than or equal to the number of threads the script is running with. */ + /** Number of threads to use for this function. + * Must be less than or equal to the number of threads the script is running with. */ threads?: number; /** Set to true this action will affect the stock market. */ stock?: boolean; @@ -540,7 +541,8 @@ export interface BitNodeMultipliers { HackExpGain: number; /** Influences how quickly the player's hacking level (not experience) scales */ HackingLevelMultiplier: number; - /** Influences how much money is produced by Hacknet Nodes and the hash rate of Hacknet Servers (unlocked in BitNode-9) */ + /** Influences how much money is produced by Hacknet Nodes + * and the hash rate of Hacknet Servers (unlocked in BitNode-9) */ HacknetNodeMoney: number; /** Influences how much money it costs to upgrade your home computer's RAM */ HomeComputerRamCost: number; @@ -548,7 +550,8 @@ export interface BitNodeMultipliers { InfiltrationMoney: number; /** Influences how much rep the player can gain from factions when selling stolen documents and secrets */ InfiltrationRep: number; - /** Influences how much money can be stolen from a server when the player performs a hack against it through the Terminal. */ + /** Influences how much money can be stolen from a server when the player + * performs a hack against it through the Terminal. */ ManualHackMoney: number; /** Influence how much it costs to purchase a server */ PurchasedServerCost: number; diff --git a/test/jest/Netscript/RamCalculation.test.ts b/test/jest/Netscript/RamCalculation.test.ts index c29a10cde..957c25fe6 100644 --- a/test/jest/Netscript/RamCalculation.test.ts +++ b/test/jest/Netscript/RamCalculation.test.ts @@ -128,7 +128,7 @@ describe("Netscript RAM Calculation/Generation Tests", function () { describe("Singularity multiplier checks", () => { sf4.lvl = 3; - const singFunctions = Object.entries(ns.singularity).filter(([key, val]) => typeof val === "function"); + const singFunctions = Object.entries(ns.singularity).filter(([__, val]) => typeof val === "function"); const singObjects = singFunctions.map(([key, val]) => { return { name: key,