This commit is contained in:
Snarling 2022-10-03 12:12:16 -04:00
parent ab56d18e1e
commit 50f14b4f58
67 changed files with 307 additions and 599 deletions

@ -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<AchievementData>;
achievements: Record<string, AchievementData>;
}
export interface AchievementData {
@ -87,7 +86,7 @@ function sfAchievement(): Achievement[] {
return achs;
}
export const achievements: IMap<Achievement> = {
export const achievements: Record<string, Achievement> = {
[FactionNames.CyberSec.toUpperCase()]: {
...achievementData[FactionNames.CyberSec.toUpperCase()],
Icon: "CSEC",

@ -1,8 +1,7 @@
import { IMap } from "./types";
import { Terminal } from "./Terminal";
export let Aliases: IMap<string> = {};
export let GlobalAliases: IMap<string> = {};
export let Aliases: Record<string, string> = {};
export let GlobalAliases: Record<string, string> = {};
export function loadAliases(saveString: string): void {
if (saveString === "") {

@ -1,4 +1,3 @@
import { Augmentation } from "./Augmentation";
import { IMap } from "../types";
export const StaticAugmentations: IMap<Augmentation> = {};
export const StaticAugmentations: Record<string, Augmentation> = {};

@ -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<BitNode> = {};
export const BitNodes: Record<string, BitNode> = {};
export function initBitNodes() {
BitNodes["BitNode1"] = new BitNode(
1,

@ -1,8 +1,7 @@
import { BlackOperation } from "./BlackOperation";
import { IMap } from "../types";
import { BlackOperationNames } from "./data/BlackOperationNames";
export const BlackOperations: IMap<BlackOperation> = {};
export const BlackOperations: Record<string, BlackOperation> = {};
(function () {
BlackOperations[BlackOperationNames.OperationTyphoon] = new BlackOperation({

@ -1,7 +1,6 @@
import { Action } from "./Action";
import { IMap } from "../types";
export const GeneralActions: IMap<Action> = {};
export const GeneralActions: Record<string, Action> = {};
const actionNames: Array<string> = [
"Training",

@ -1,8 +1,7 @@
import { Skill } from "./Skill";
import { SkillNames } from "./data/SkillNames";
import { IMap } from "../types";
export const Skills: IMap<Skill> = {};
export const Skills: Record<string, Skill> = {};
(function () {
Skills[SkillNames.BladesIntuition] = new Skill({

@ -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<CodingContractType> = {};
export const CodingContractTypes: Record<string, CodingContractType> = {};
for (const md of codingContractTypesMetadata) {
// tslint:disable-next-line

@ -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<Company> = {};
export let Companies: Record<string, Company> = {};
function addCompany(params: IConstructorParams): void {
if (Companies[params.name] != null) {

@ -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<boolean>;
companyPositions: Record<string, boolean>;
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<boolean>;
companyPositions: Record<string, boolean>;
/**
* Company-specific multiplier for earnings

@ -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<CompanyPosition> = {};
export const CompanyPositions: Record<string, CompanyPosition> = {};
function addCompanyPosition(params: IConstructorParams): void {
if (CompanyPositions[params.name] != null) {

@ -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<boolean> = {};
const AllITPositions: IMap<boolean> = {};
const AllNetworkEngineerPositions: IMap<boolean> = {};
const SecurityEngineerPositions: IMap<boolean> = {};
const AllTechnologyPositions: IMap<boolean> = {};
const AllBusinessPositions: IMap<boolean> = {};
const AllAgentPositions: IMap<boolean> = {};
const AllSecurityPositions: IMap<boolean> = {};
const AllSoftwareConsultantPositions: IMap<boolean> = {};
const AllBusinessConsultantPositions: IMap<boolean> = {};
const SoftwarePositionsUpToHeadOfEngineering: IMap<boolean> = {};
const SoftwarePositionsUpToLeadDeveloper: IMap<boolean> = {};
const BusinessPositionsUpToOperationsManager: IMap<boolean> = {};
const WaiterOnly: IMap<boolean> = {};
const EmployeeOnly: IMap<boolean> = {};
const PartTimeWaiterOnly: IMap<boolean> = {};
const PartTimeEmployeeOnly: IMap<boolean> = {};
const OperationsManagerOnly: IMap<boolean> = {};
const CEOOnly: IMap<boolean> = {};
const AllSoftwarePositions: Record<string, boolean> = {};
const AllITPositions: Record<string, boolean> = {};
const AllNetworkEngineerPositions: Record<string, boolean> = {};
const SecurityEngineerPositions: Record<string, boolean> = {};
const AllTechnologyPositions: Record<string, boolean> = {};
const AllBusinessPositions: Record<string, boolean> = {};
const AllAgentPositions: Record<string, boolean> = {};
const AllSecurityPositions: Record<string, boolean> = {};
const AllSoftwareConsultantPositions: Record<string, boolean> = {};
const AllBusinessConsultantPositions: Record<string, boolean> = {};
const SoftwarePositionsUpToHeadOfEngineering: Record<string, boolean> = {};
const SoftwarePositionsUpToLeadDeveloper: Record<string, boolean> = {};
const BusinessPositionsUpToOperationsManager: Record<string, boolean> = {};
const WaiterOnly: Record<string, boolean> = {};
const EmployeeOnly: Record<string, boolean> = {};
const PartTimeWaiterOnly: Record<string, boolean> = {};
const PartTimeEmployeeOnly: Record<string, boolean> = {};
const OperationsManagerOnly: Record<string, boolean> = {};
const CEOOnly: Record<string, boolean> = {};
posNames.SoftwareCompanyPositions.forEach((e) => {
AllSoftwarePositions[e] = true;

@ -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);
}

@ -1,6 +1,4 @@
import { IMap } from "../types";
export const EmployeePositions: IMap<string> = {
export const EmployeePositions = {
Operations: "Operations",
Engineer: "Engineer",
Business: "Business",
@ -8,4 +6,4 @@ export const EmployeePositions: IMap<string> = {
RandD: "Research & Development",
Training: "Training",
Unassigned: "Unassigned",
};
} as const;

@ -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<number> = {
export const MaterialSizes: Record<string, number> = {
Water: 0.05,
Energy: 0.01,
Food: 0.03,

@ -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<number>;
req?: Record<string, number>;
}
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<number[]> = createCityMap<number[]>([0, 0, 0]);
data: Record<string, number[]> = createCityMap<number[]>([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<number> = {};
reqMats: Record<string, number> = {};
// 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<any[]> = createCityMap<any[]>([false, 0]);
sllman: IMap<any[]> = createCityMap<any[]>([false, 0]);
prdman: Record<string, any[]> = createCityMap<any[]>([false, 0]);
sllman: Record<string, any[]> = createCityMap<any[]>([false, 0]);
// Flags that signal whether automatic sale pricing through Market TA is enabled
marketTa1 = false;
marketTa2 = false;
marketTa2Price: IMap<number> = createCityMap<number>(0);
marketTa2Price: Record<string, number> = createCityMap<number>(0);
// Determines the maximum amount of this product that can be sold in one market cycle
maxsll = 0;

@ -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<any> = {
export const ProductRatingWeights: Record<string, IProductRatingWeight> = {
[Industries.Food]: {
Quality: 0.7,
Durability: 0.1,

@ -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<Research> = {};
export const ResearchMap: Record<string, Research> = {};
function addResearch(p: IConstructorParams): void {
if (ResearchMap[p.name] != null) {

@ -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<boolean> = {};
researched: Record<string, boolean> = {};
// Root Node
root: Node | null = null;

@ -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<Material>;
materials: Record<string, Material>;
// Maximum amount warehouse can hold
size: number;

@ -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<Crime> = {
export const Crimes: Record<string, Crime> = {
Shoplift: new Crime("Shoplift", "to shoplift", CrimeType.SHOPLIFT, 2e3, 15e3, 1 / 20, 0.1, {
dexterity_success_weight: 1,
agility_success_weight: 1,

@ -1,8 +1,7 @@
import { DarkWebItem } from "./DarkWebItem";
import { IMap } from "../types";
import { Programs, initPrograms } from "../Programs/Programs";
export const DarkWebItems: IMap<DarkWebItem> = {};
export const DarkWebItems: Record<string, DarkWebItem> = {};
export function initDarkWebItems() {
initPrograms();
Object.assign(DarkWebItems, {

@ -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);
}
}

@ -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<string, (s: string) => 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);
}
});
}

@ -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<FactionInfo> = {
export const FactionInfos: Record<string, FactionInfo> = {
// Endgame
[FactionNames.Illuminati]: new FactionInfo({
infoText: (

@ -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<Faction> = {};
export let Factions: Record<string, Faction> = {};
export function loadFactions(saveString: string): void {
Factions = JSON.parse(saveString, Reviver);

@ -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);

@ -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<number> = {};
upgrades: Record<string, number> = {};
constructor() {
for (const name of Object.keys(HashUpgrades)) {

@ -4,9 +4,8 @@
*/
import { HashUpgrade, IConstructorParams } from "./HashUpgrade";
import { HashUpgradesMetadata } from "./data/HashUpgradesMetadata";
import { IMap } from "../types";
export const HashUpgrades: IMap<HashUpgrade> = {};
export const HashUpgrades: Record<string, HashUpgrade> = {};
function createHashUpgrade(p: IConstructorParams): void {
HashUpgrades[p.name] = new HashUpgrade(p);

@ -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<Literature> = {};
export const Literatures: Record<string, Literature> = {};
(function () {
let title, fn, txt;

@ -1,6 +1,4 @@
import { IMap } from "../../types";
export const LiteratureNames: IMap<string> = {
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<string> = {
TheNewGod: "the-new-god.lit",
NewTriads: "new-triads.lit",
TheSecretWar: "the-secret-war.lit",
};
} as const;

@ -3,6 +3,5 @@
* Key = City Name, Value = City object
*/
import { City } from "./City";
import { IMap } from "../types";
export const Cities: IMap<City> = {};
export const Cities: Record<string, City> = {};

@ -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<Location> = {};
export const Locations: Record<string, Location> = {};
/**
* Here, we'll initialize both Locations and Cities data. These can both

@ -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<T>(initValue: T): IMap<T> {
const map: IMap<T> = {};
export function createCityMap<T>(initValue: T): Record<string, T> {
const map: Record<string, T> = {};
const cities = Object.keys(Cities);
for (let i = 0; i < cities.length; ++i) {
map[cities[i]] = initValue;

@ -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) {

@ -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<API> = {
// TODO remember to update RamCalculations.js and WorkerScript.js
// RAM costs for Netscript functions
export const RamCostConstants: IMap<number> = {
export const RamCostConstants: Record<string, number> = {
ScriptBaseRamCost: 1.6,
ScriptDomRamCost: 25,
ScriptCorporationRamCost: 1024 - 1.6,
@ -604,7 +603,7 @@ const SourceRamCosts = {
},
};
export const RamCosts: IMap<any> = SourceRamCosts;
export const RamCosts: Record<string, any> = 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

@ -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<boolean> = {};
disableLogs: Record<string, boolean> = {};
/**
* 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<boolean> = {};
dynamicLoadedFns: Record<string, boolean> = {};
/**
* 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<boolean> = {};
loadedFns: Record<string, boolean> = {};
/**
* Filename of script

@ -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<NS> = {
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<NS> = {
},
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:

@ -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<NSCorporation> {
function createCorporation(corporationName: string, selfFund = true): boolean {
@ -711,7 +712,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
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<NSCorporation> {
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);

@ -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<IInfiltration> {
);
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)

@ -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<ISleeve> {
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}'.`);

@ -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<string> = {};
jobs: Record<string, string> = {};
karma = 0;
numPeopleKilled = 0;
location = LocationName.TravelAgency;

@ -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);
}
}

@ -1,8 +1,7 @@
import { Program } from "./Program";
import { programsMetadata } from "./data/ProgramsMetadata";
import { IMap } from "../types";
export const Programs: IMap<Program> = {};
export const Programs: Record<string, Program> = {};
export function initPrograms() {
for (const params of programsMetadata) {
Programs[params.key] = new Program(params.name, params.create, params.run);

@ -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),
);
}
}

@ -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 {

@ -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<number[]> = {};
dataMap: Record<string, number[]> = {};
// Script filename
filename = "";

@ -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

@ -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<Server | HacknetServer> = {};
let AllServers: Record<string, Server | HacknetServer> = {};
function GetServerByIP(ip: string): BaseServer | undefined {
for (const key of Object.keys(AllServers)) {

@ -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",
/** Word wrap setting for Script Editor. */
MonacoWordWrap: "off" as WordWrapOptions,
theme: { ...defaultTheme },
styles: { ...defaultStyles },
overview: defaultSettings.overview,
EditorTheme: { ...defaultMonacoTheme },
init() {
Object.assign(Settings, defaultSettings);
},
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);
},
};

@ -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<SourceFile> = {};
export const SourceFiles: Record<string, SourceFile> = {};
/** Engine initializer for SourceFiles, BitNodes, and BitNodeMultipliers. Run once at engine load. */
export function initSourceFiles() {
initBitNodes();

@ -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<Stock>;
symbolToStockMap: Record<string, Stock>;
}
/**

@ -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<Stock> = {}; // Maps symbol -> Stock object
export const SymbolToStockMap: Record<string, Stock> = {}; // 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<keyof typeof StockSymbols>) {
if (StockSymbols.hasOwnProperty(name)) {
const stock = StockMarket[name];
if (stock == null) {

@ -1,41 +1,40 @@
import { IMap } from "../../types";
import { LocationName } from "../../Locations/data/LocationNames";
export const StockSymbols: IMap<string> = {};
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;

@ -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<keyof typeof StockSymbols>) {
TickerHeaderFormatData.longestName = Math.max(key.length, TickerHeaderFormatData.longestName);
TickerHeaderFormatData.longestSymbol = Math.max(StockSymbols[key].length, TickerHeaderFormatData.longestSymbol);
}

@ -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, (command: string) => string[]> = {
scriptEditor: (command) => {
return [
`Usage: ${command} [file ...] | [glob]`,
@ -70,7 +69,7 @@ const TemplatedHelpTexts: IMap<(command: string) => string[]> = {
},
};
export const HelpTexts: IMap<string[]> = {
export const HelpTexts: Record<string, string[]> = {
alias: [
'Usage: alias [-g] [name="value"] ',
" ",

@ -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;
}

@ -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<IPredefinedTheme> => ({
export const getPredefinedThemes = (): Record<string, IPredefinedTheme> => ({
...predefined,
});

@ -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
</Button>
</>,
ToastVariant.INFO,
"info",
30000,
);
}

@ -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"]}
/>
<ColorEditor
name="primary"
onColorChange={onColorChange}
color={customTheme["primary"]}
defaultColor={defaultSettings.theme["primary"]}
defaultColor={defaultTheme["primary"]}
/>
<ColorEditor
name="primarydark"
onColorChange={onColorChange}
color={customTheme["primarydark"]}
defaultColor={defaultSettings.theme["primarydark"]}
defaultColor={defaultTheme["primarydark"]}
/>
<br />
@ -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"]}
/>
<ColorEditor
name="success"
onColorChange={onColorChange}
color={customTheme["success"]}
defaultColor={defaultSettings.theme["success"]}
defaultColor={defaultTheme["success"]}
/>
<ColorEditor
name="successdark"
onColorChange={onColorChange}
color={customTheme["successdark"]}
defaultColor={defaultSettings.theme["successdark"]}
defaultColor={defaultTheme["successdark"]}
/>
<br />
@ -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"]}
/>
<ColorEditor
name="error"
onColorChange={onColorChange}
color={customTheme["error"]}
defaultColor={defaultSettings.theme["error"]}
defaultColor={defaultTheme["error"]}
/>
<ColorEditor
name="errordark"
onColorChange={onColorChange}
color={customTheme["errordark"]}
defaultColor={defaultSettings.theme["errordark"]}
defaultColor={defaultTheme["errordark"]}
/>
<br />
@ -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"]}
/>
<ColorEditor
name="secondary"
onColorChange={onColorChange}
color={customTheme["secondary"]}
defaultColor={defaultSettings.theme["secondary"]}
defaultColor={defaultTheme["secondary"]}
/>
<ColorEditor
name="secondarydark"
onColorChange={onColorChange}
color={customTheme["secondarydark"]}
defaultColor={defaultSettings.theme["secondarydark"]}
defaultColor={defaultTheme["secondarydark"]}
/>
<br />
@ -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"]}
/>
<ColorEditor
name="warning"
onColorChange={onColorChange}
color={customTheme["warning"]}
defaultColor={defaultSettings.theme["warning"]}
defaultColor={defaultTheme["warning"]}
/>
<ColorEditor
name="warningdark"
onColorChange={onColorChange}
color={customTheme["warningdark"]}
defaultColor={defaultSettings.theme["warningdark"]}
defaultColor={defaultTheme["warningdark"]}
/>
<br />
@ -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"]}
/>
<ColorEditor
name="info"
onColorChange={onColorChange}
color={customTheme["info"]}
defaultColor={defaultSettings.theme["info"]}
defaultColor={defaultTheme["info"]}
/>
<ColorEditor
name="infodark"
onColorChange={onColorChange}
color={customTheme["infodark"]}
defaultColor={defaultSettings.theme["infodark"]}
defaultColor={defaultTheme["infodark"]}
/>
<br />
@ -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"]}
/>
<ColorEditor
name="well"
onColorChange={onColorChange}
color={customTheme["well"]}
defaultColor={defaultSettings.theme["well"]}
defaultColor={defaultTheme["well"]}
/>
<ColorEditor
name="white"
onColorChange={onColorChange}
color={customTheme["white"]}
defaultColor={defaultSettings.theme["white"]}
defaultColor={defaultTheme["white"]}
/>
<ColorEditor
name="black"
onColorChange={onColorChange}
color={customTheme["black"]}
defaultColor={defaultSettings.theme["black"]}
defaultColor={defaultTheme["black"]}
/>
<ColorEditor
name="backgroundprimary"
onColorChange={onColorChange}
color={customTheme["backgroundprimary"]}
defaultColor={defaultSettings.theme["backgroundprimary"]}
defaultColor={defaultTheme["backgroundprimary"]}
/>
<ColorEditor
name="backgroundsecondary"
onColorChange={onColorChange}
color={customTheme["backgroundsecondary"]}
defaultColor={defaultSettings.theme["backgroundsecondary"]}
defaultColor={defaultTheme["backgroundsecondary"]}
/>
<ColorEditor
name="button"
onColorChange={onColorChange}
color={customTheme["button"]}
defaultColor={defaultSettings.theme["button"]}
defaultColor={defaultTheme["button"]}
/>
<br />
@ -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"]}
/>
<ColorEditor
name="money"
onColorChange={onColorChange}
color={customTheme["money"]}
defaultColor={defaultSettings.theme["money"]}
defaultColor={defaultTheme["money"]}
/>
<ColorEditor
name="hack"
onColorChange={onColorChange}
color={customTheme["hack"]}
defaultColor={defaultSettings.theme["hack"]}
defaultColor={defaultTheme["hack"]}
/>
<ColorEditor
name="combat"
onColorChange={onColorChange}
color={customTheme["combat"]}
defaultColor={defaultSettings.theme["combat"]}
defaultColor={defaultTheme["combat"]}
/>
<ColorEditor
name="cha"
onColorChange={onColorChange}
color={customTheme["cha"]}
defaultColor={defaultSettings.theme["cha"]}
defaultColor={defaultTheme["cha"]}
/>
<ColorEditor
name="int"
onColorChange={onColorChange}
color={customTheme["int"]}
defaultColor={defaultSettings.theme["int"]}
defaultColor={defaultTheme["int"]}
/>
<ColorEditor
name="rep"
onColorChange={onColorChange}
color={customTheme["rep"]}
defaultColor={defaultSettings.theme["rep"]}
defaultColor={defaultTheme["rep"]}
/>
<ColorEditor
name="disabled"
onColorChange={onColorChange}
color={customTheme["disabled"]}
defaultColor={defaultSettings.theme["disabled"]}
defaultColor={defaultTheme["disabled"]}
/>
</Paper>

@ -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 {
</Button>
</>
);
SnackbarEvents.emit(warningToast, ToastVariant.WARNING, 5000);
SnackbarEvents.emit(warningToast, "warning", 5000);
}
export { Engine };

@ -1,35 +1,8 @@
/**
* Performs an equality check between two instances of the same type.
*/
export type EqualityFunc<T> = (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> = T[keyof T];
/**
* A map is an object that holds a mapping between string keys and some consistent type.
*/
export interface IMap<T> {
[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, T2> = [T1] extends [T2] ? ([T2] extends [T1] ? true : false) : false;
/**
* Status object for functions that return a boolean indicating success/failure

@ -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: {

@ -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<string> = (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++;
}

@ -1,6 +0,0 @@
export function checkEnum<T extends string, TEnumValue extends string>(
enumVariable: { [key in T]: TEnumValue },
value: string,
): value is TEnumValue {
return Object.values(enumVariable).includes(value);
}

@ -0,0 +1,7 @@
// This works for both enums and regular objects.
export function checkObjContainsValue<T extends Record<string, string>>(
obj: T,
value: string,
): value is T[keyof T] {
return Object.values(obj).includes(value);
}

@ -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<any> = {};
const initialValues: Record<string, any> = {};
for (const stockName in StockMarket) {
const stock = StockMarket[stockName];
if (!(stock instanceof Stock)) {