mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-17 13:13:49 +01:00
CODEBASE: Fix lint errors 2 (#1756)
This commit is contained in:
parent
e3c10e9f0f
commit
36c143b687
@ -35,6 +35,7 @@ module.exports = {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"react/no-unescaped-entities": "off",
|
||||
"@typescript-eslint/restrict-template-expressions": "off",
|
||||
"@typescript-eslint/no-unsafe-enum-comparison": "off",
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
|
11
src/@types/global.d.ts
vendored
11
src/@types/global.d.ts
vendored
@ -49,3 +49,14 @@ declare global {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module "monaco-vim" {
|
||||
export const initVimMode: (...args: unknown[]) => { dispose: () => void };
|
||||
export const VimMode: {
|
||||
Vim: {
|
||||
defineEx: (...args: unknown[]) => void;
|
||||
mapCommand: (...args: unknown[]) => void;
|
||||
defineAction: (...args: unknown[]) => void;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { Card, Suit } from "./Card";
|
||||
|
||||
import { makeStyles } from "tss-react/mui";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import { throwIfReachable } from "../../utils/helpers/throwIfReachable";
|
||||
|
||||
interface Props {
|
||||
card: Card;
|
||||
@ -51,7 +52,7 @@ export const ReactCard: FC<Props> = ({ card, hidden }) => {
|
||||
suit = <span>♠</span>;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`MissingCaseException: ${card.suit}`);
|
||||
throwIfReachable(card.suit);
|
||||
}
|
||||
return (
|
||||
<Paper className={`${classes.card} ${card.isRedSuit() ? classes.red : classes.black}`}>
|
||||
|
@ -2,13 +2,15 @@ import { Company } from "./Company";
|
||||
import { CompanyPosition } from "./CompanyPosition";
|
||||
|
||||
import { PlayerCondition, haveSkill, haveCompanyRep } from "../Faction/FactionJoinCondition";
|
||||
import type { Skills } from "../PersonObjects/Skills";
|
||||
import { getRecordEntries } from "../Types/Record";
|
||||
|
||||
export function getJobRequirements(company: Company, pos: CompanyPosition): PlayerCondition[] {
|
||||
const reqSkills = pos.requiredSkills(company.jobStatReqOffset);
|
||||
const reqs = [];
|
||||
for (const [skillName, value] of Object.entries(reqSkills)) {
|
||||
if (value > 0) reqs.push(haveSkill(skillName as keyof Skills, value));
|
||||
for (const [skillName, value] of getRecordEntries(reqSkills)) {
|
||||
if (value > 0) {
|
||||
reqs.push(haveSkill(skillName, value));
|
||||
}
|
||||
}
|
||||
if (pos.requiredReputation > 0) {
|
||||
reqs.push(haveCompanyRep(company.name, pos.requiredReputation));
|
||||
|
@ -17,7 +17,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||
import { JSONMap, JSONSet } from "../Types/Jsonable";
|
||||
import { formatMoney } from "../ui/formatNumber";
|
||||
import { isPositiveInteger } from "../types";
|
||||
import { isPositiveInteger, type Result } from "../types";
|
||||
import { createEnumKeyedRecord, getRecordValues } from "../Types/Record";
|
||||
import { getKeyList } from "../utils/helpers/getKeyList";
|
||||
|
||||
@ -372,29 +372,56 @@ export class Corporation {
|
||||
}
|
||||
}
|
||||
|
||||
/** Purchasing a one-time unlock
|
||||
* @returns A string on failure, indicating the reason for failure. */
|
||||
purchaseUnlock(unlockName: CorpUnlockName): string | void {
|
||||
if (this.unlocks.has(unlockName)) return `The corporation has already unlocked ${unlockName}`;
|
||||
/**
|
||||
* Purchasing a one-time unlock
|
||||
*/
|
||||
purchaseUnlock(unlockName: CorpUnlockName): Result {
|
||||
if (this.unlocks.has(unlockName)) {
|
||||
return {
|
||||
success: false,
|
||||
message: `${unlockName} has already been unlocked.`,
|
||||
};
|
||||
}
|
||||
const price = CorpUnlocks[unlockName].price;
|
||||
if (this.funds < price) return `Insufficient funds to purchase ${unlockName}, requires ${formatMoney(price)}`;
|
||||
if (this.funds < price) {
|
||||
return {
|
||||
success: false,
|
||||
message: `Insufficient funds to purchase ${unlockName}, requires ${formatMoney(price)}.`,
|
||||
};
|
||||
}
|
||||
this.loseFunds(price, "upgrades");
|
||||
this.unlocks.add(unlockName);
|
||||
|
||||
// Apply effects for one-time unlocks
|
||||
if (unlockName === CorpUnlockName.ShadyAccounting) this.dividendTax -= 0.05;
|
||||
if (unlockName === CorpUnlockName.GovernmentPartnership) this.dividendTax -= 0.1;
|
||||
if (unlockName === CorpUnlockName.ShadyAccounting) {
|
||||
this.dividendTax -= 0.05;
|
||||
}
|
||||
if (unlockName === CorpUnlockName.GovernmentPartnership) {
|
||||
this.dividendTax -= 0.1;
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
|
||||
/** Purchasing a levelable upgrade
|
||||
* @returns A string on failure, indicating the reason for failure. */
|
||||
purchaseUpgrade(upgradeName: CorpUpgradeName, amount = 1): string | void {
|
||||
/**
|
||||
* Purchasing a levelable upgrade
|
||||
*/
|
||||
purchaseUpgrade(upgradeName: CorpUpgradeName, amount = 1): Result {
|
||||
if (!isPositiveInteger(amount)) {
|
||||
return `Number of upgrade levels purchased must be a positive integer (attempted: ${amount}).`;
|
||||
return {
|
||||
success: false,
|
||||
message: `Number of upgrade levels purchased must be a positive integer (attempted: ${amount}).`,
|
||||
};
|
||||
}
|
||||
const upgrade = CorpUpgrades[upgradeName];
|
||||
const totalCost = calculateUpgradeCost(this, upgrade, amount);
|
||||
if (this.funds < totalCost) return `Not enough funds to purchase ${amount} of upgrade ${upgradeName}.`;
|
||||
if (this.funds < totalCost) {
|
||||
return {
|
||||
success: false,
|
||||
message: `Not enough funds to purchase ${amount} of upgrade ${upgradeName}.`,
|
||||
};
|
||||
}
|
||||
this.loseFunds(totalCost, "upgrades");
|
||||
this.upgrades[upgradeName].level += amount;
|
||||
this.upgrades[upgradeName].value += upgrade.benefit * amount;
|
||||
@ -407,6 +434,9 @@ export class Corporation {
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
}
|
||||
|
||||
getProductionMultiplier(): number {
|
||||
|
@ -16,6 +16,7 @@ import { PartialRecord, getRecordEntries, getRecordKeys, getRecordValues } from
|
||||
import { Material } from "./Material";
|
||||
import { getKeyList } from "../utils/helpers/getKeyList";
|
||||
import { calculateMarkupMultiplier } from "./helpers";
|
||||
import { throwIfReachable } from "../utils/helpers/throwIfReachable";
|
||||
|
||||
interface DivisionParams {
|
||||
name: string;
|
||||
@ -704,8 +705,7 @@ export class Division {
|
||||
case "START":
|
||||
break;
|
||||
default:
|
||||
console.error(`Invalid state: ${state}`);
|
||||
break;
|
||||
throwIfReachable(state);
|
||||
} //End switch(this.state)
|
||||
this.updateWarehouseSizeUsed(warehouse);
|
||||
}
|
||||
@ -936,8 +936,7 @@ export class Division {
|
||||
case "EXPORT":
|
||||
break;
|
||||
default:
|
||||
console.error(`Invalid State: ${state}`);
|
||||
break;
|
||||
throwIfReachable(state);
|
||||
} //End switch(this.state)
|
||||
this.updateWarehouseSizeUsed(warehouse);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { Division } from "./Division";
|
||||
import { Corporation } from "./Corporation";
|
||||
import { getRandomIntInclusive } from "../utils/helpers/getRandomIntInclusive";
|
||||
import { createEnumKeyedRecord, getRecordKeys } from "../Types/Record";
|
||||
import { throwIfReachable } from "../utils/helpers/throwIfReachable";
|
||||
|
||||
interface IParams {
|
||||
city: CityName;
|
||||
@ -165,8 +166,7 @@ export class OfficeSpace {
|
||||
case "total":
|
||||
continue;
|
||||
default:
|
||||
console.error(`Invalid employee position: ${name}`);
|
||||
break;
|
||||
throwIfReachable(name);
|
||||
}
|
||||
this.employeeProductionByJob[name] = this.employeeJobs[name] * prodMult * prodBase;
|
||||
total += this.employeeProductionByJob[name];
|
||||
|
@ -214,7 +214,9 @@ export class Product {
|
||||
|
||||
calculateRating(industry: Division): void {
|
||||
const weights = IndustriesData[industry.type].product?.ratingWeights;
|
||||
if (!weights) return console.error(`Could not find product rating weights for: ${industry}`);
|
||||
if (!weights) {
|
||||
return console.error(`Could not find product rating weights for: ${industry.name}`);
|
||||
}
|
||||
this.rating = getRecordEntries(weights).reduce(
|
||||
(total, [statName, weight]) => total + this.stats[statName] * weight,
|
||||
0,
|
||||
|
@ -31,8 +31,10 @@ export function LevelableUpgrade({ upgradeName, mult, rerender }: IProps): React
|
||||
const tooltip = data.desc;
|
||||
function onClick(): void {
|
||||
if (corp.funds < cost) return;
|
||||
const message = corp.purchaseUpgrade(upgradeName, amount);
|
||||
if (message) dialogBoxCreate(`Could not upgrade ${upgradeName} ${amount} times:\n${message}`);
|
||||
const result = corp.purchaseUpgrade(upgradeName, amount);
|
||||
if (!result.success) {
|
||||
dialogBoxCreate(`Could not upgrade ${upgradeName} ${amount} times:\n${result.message}`);
|
||||
}
|
||||
rerender();
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,10 @@ export function Unlock(props: UnlockProps): React.ReactElement {
|
||||
|
||||
function onClick(): void {
|
||||
// corp.unlock handles displaying a dialog on failure
|
||||
const message = corp.purchaseUnlock(props.name);
|
||||
if (message) dialogBoxCreate(`Error while attempting to purchase ${props.name}:\n${message}`);
|
||||
const result = corp.purchaseUnlock(props.name);
|
||||
if (!result.success) {
|
||||
dialogBoxCreate(`Error while attempting to purchase ${props.name}:\n${result.message}`);
|
||||
}
|
||||
// Rerenders the parent, which should remove this item if the purchase was successful
|
||||
props.rerender();
|
||||
}
|
||||
|
@ -44,8 +44,8 @@ export function SellSharesModal(props: IProps): React.ReactElement {
|
||||
props.onClose();
|
||||
props.rerender();
|
||||
setShares(NaN);
|
||||
} catch (err) {
|
||||
dialogBoxCreate(`${err as Error}`);
|
||||
} catch (error) {
|
||||
dialogBoxCreate(String(error));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,17 +7,17 @@ export let staneksGift = new StaneksGift();
|
||||
|
||||
export function loadStaneksGift(saveString: string): void {
|
||||
if (saveString) {
|
||||
staneksGift = JSON.parse(saveString, Reviver);
|
||||
staneksGift = JSON.parse(saveString, Reviver) as StaneksGift;
|
||||
} else {
|
||||
staneksGift = new StaneksGift();
|
||||
}
|
||||
}
|
||||
|
||||
export function zeros(width: number, height: number): number[][] {
|
||||
const array = [];
|
||||
const array: number[][] = [];
|
||||
|
||||
for (let i = 0; i < width; ++i) {
|
||||
array.push(Array(height).fill(0));
|
||||
array.push(Array<number>(height).fill(0));
|
||||
}
|
||||
|
||||
return array;
|
||||
|
@ -18,9 +18,6 @@ export class StaneksGift extends BaseGift {
|
||||
isBonusCharging = false;
|
||||
justCharged = true;
|
||||
storedCycles = 0;
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
baseSize(): number {
|
||||
return StanekConstants.BaseSize + currentNodeMults.StaneksGiftExtraSize + Player.activeSourceFileLvl(13);
|
||||
|
@ -155,13 +155,27 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
|
||||
>
|
||||
<Button onClick={startImport} startIcon={<Upload />} sx={{ gridArea: "import" }}>
|
||||
Import Game
|
||||
<input ref={importInput} id="import-game-file-selector" type="file" hidden onChange={onImport} />
|
||||
<input
|
||||
ref={importInput}
|
||||
id="import-game-file-selector"
|
||||
type="file"
|
||||
hidden
|
||||
onChange={(event) => {
|
||||
onImport(event).catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<ConfirmationModal
|
||||
open={importSaveOpen}
|
||||
onClose={() => setImportSaveOpen(false)}
|
||||
onConfirm={() => confirmedImportGame()}
|
||||
onConfirm={() => {
|
||||
confirmedImportGame().catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
}}
|
||||
additionalButton={<Button onClick={compareSaveGame}>Compare Save</Button>}
|
||||
confirmationText={
|
||||
<>
|
||||
|
@ -15,6 +15,7 @@ import { Settings } from "../../Settings/Settings";
|
||||
import { MoneyRate } from "../../ui/React/MoneyRate";
|
||||
import { StatsRow } from "../../ui/React/StatsRow";
|
||||
import { useStyles } from "../../ui/React/CharacterOverview";
|
||||
import { getKeyFromReactElements } from "../../utils/StringHelperFunctions";
|
||||
|
||||
interface IProps {
|
||||
member: GangMember;
|
||||
@ -103,7 +104,7 @@ export function GangMemberStats(props: IProps): React.ReactElement {
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{data.map(([a, b]) => (
|
||||
<TableRow key={a.toString() + b.toString()}>
|
||||
<TableRow key={getKeyFromReactElements(a, b)}>
|
||||
<TableCell classes={{ root: classes.cellNone }}>
|
||||
<Typography>{a}</Typography>
|
||||
</TableCell>
|
||||
|
@ -83,7 +83,11 @@ export function loadGo(data: unknown): boolean {
|
||||
Go.storeCycles(loadStoredCycles(parsedData.storedCycles));
|
||||
|
||||
// If it's the AI's turn, initiate their turn, which will populate nextTurn
|
||||
if (currentGame.previousPlayer === GoColor.black && currentGame.ai !== GoOpponent.none) makeAIMove(currentGame);
|
||||
if (currentGame.previousPlayer === GoColor.black && currentGame.ai !== GoOpponent.none) {
|
||||
makeAIMove(currentGame).catch((error) => {
|
||||
showError(error);
|
||||
});
|
||||
}
|
||||
// If it's not the AI's turn and we're not in gameover status, initialize nextTurn promise based on the previous move/pass
|
||||
else if (currentGame.previousPlayer) {
|
||||
const previousMove = getPreviousMove();
|
||||
|
@ -135,7 +135,7 @@ export function MinesweeperGame(props: IMinigameProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<Typography
|
||||
key={`${item}${uniqueId()}`}
|
||||
key={uniqueId()}
|
||||
sx={{
|
||||
color: color,
|
||||
border: `2px solid ${item.current ? Settings.theme.infolight : Settings.theme.primary}`,
|
||||
|
@ -66,7 +66,7 @@ class NSProxyHandler<API extends GenericAPI<API>> {
|
||||
|
||||
const descriptor = Object.getOwnPropertyDescriptor(this.ns, key);
|
||||
if (!descriptor) return descriptor;
|
||||
const field = descriptor.value;
|
||||
const field: unknown = descriptor.value;
|
||||
|
||||
if (typeof field === "function") {
|
||||
const arrayPath = [...this.tree, key];
|
||||
@ -74,7 +74,7 @@ class NSProxyHandler<API extends GenericAPI<API>> {
|
||||
const ctx = { workerScript: this.ws, function: key, functionPath };
|
||||
// Only do the context-binding once, instead of each time the function
|
||||
// is called.
|
||||
const func: any = field(ctx);
|
||||
const func = field(ctx) as (...args: unknown[]) => unknown;
|
||||
const wrappedFunction = function (...args: unknown[]): unknown {
|
||||
// What remains *must* be called every time.
|
||||
helpers.checkEnvFlags(ctx);
|
||||
|
@ -692,8 +692,11 @@ function getRunningScript(ctx: NetscriptContext, ident: ScriptIdentifier): Runni
|
||||
return findRunningScriptByPid(ident);
|
||||
} else {
|
||||
const scripts = getRunningScriptsByArgs(ctx, ident.scriptname, ident.hostname, ident.args);
|
||||
if (scripts === null) return null;
|
||||
return scripts.values().next().value ?? null;
|
||||
if (scripts === null) {
|
||||
return null;
|
||||
}
|
||||
const next = scripts.values().next();
|
||||
return !next.done ? next.value : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,15 +624,19 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
checkAccess(ctx);
|
||||
const unlockName = getEnumHelper("CorpUnlockName").nsGetMember(ctx, _unlockName, "unlockName");
|
||||
const corporation = getCorporation();
|
||||
const message = corporation.purchaseUnlock(unlockName);
|
||||
if (message) throw new Error(`Could not unlock ${unlockName}: ${message}`);
|
||||
const result = corporation.purchaseUnlock(unlockName);
|
||||
if (!result.success) {
|
||||
throw new Error(`Could not unlock ${unlockName}: ${result.message}`);
|
||||
}
|
||||
},
|
||||
levelUpgrade: (ctx) => (_upgradeName) => {
|
||||
checkAccess(ctx);
|
||||
const upgradeName = getEnumHelper("CorpUpgradeName").nsGetMember(ctx, _upgradeName, "upgradeName");
|
||||
const corporation = getCorporation();
|
||||
const message = corporation.purchaseUpgrade(upgradeName, 1);
|
||||
if (message) throw new Error(`Could not upgrade ${upgradeName}: ${message}`);
|
||||
const result = corporation.purchaseUpgrade(upgradeName, 1);
|
||||
if (!result.success) {
|
||||
throw new Error(`Could not upgrade ${upgradeName}: ${result.message}`);
|
||||
}
|
||||
},
|
||||
issueDividends: (ctx) => (_rate) => {
|
||||
checkAccess(ctx);
|
||||
|
@ -13,6 +13,7 @@ import { Factions } from "../Faction/Factions";
|
||||
import { getEnumHelper } from "../utils/EnumHelper";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
import { filterTruthy } from "../utils/helpers/ArrayHelpers";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
|
||||
export function NetscriptInfiltration(): InternalAPI<NetscriptInfiltation> {
|
||||
const getLocationsWithInfiltrations = Object.values(Locations).filter(
|
||||
@ -21,16 +22,29 @@ export function NetscriptInfiltration(): InternalAPI<NetscriptInfiltation> {
|
||||
|
||||
const calculateInfiltrationData = (ctx: NetscriptContext, locationName: LocationName): InfiltrationLocation => {
|
||||
const location = Locations[locationName];
|
||||
if (location === undefined) throw helpers.errorMessage(ctx, `Location '${location}' does not exists.`);
|
||||
if (location.infiltrationData === undefined)
|
||||
throw helpers.errorMessage(ctx, `Location '${location}' does not provide infiltrations.`);
|
||||
if (location === undefined) {
|
||||
throw helpers.errorMessage(ctx, `Location "${locationName}" does not exist.`);
|
||||
}
|
||||
if (location.infiltrationData === undefined) {
|
||||
throw helpers.errorMessage(ctx, `Location "${locationName}" does not provide infiltrations.`);
|
||||
}
|
||||
const locationCity = location.city;
|
||||
/**
|
||||
* location.city is only null when the location is available in all cities. This kind of location does not have
|
||||
* infiltration data.
|
||||
*/
|
||||
if (locationCity === null) {
|
||||
const errorMessage = `Location "${locationName}" is available in all cities, but it still has infiltration data.`;
|
||||
exceptionAlert(new Error(errorMessage));
|
||||
throw helpers.errorMessage(ctx, errorMessage);
|
||||
}
|
||||
const startingSecurityLevel = location.infiltrationData.startingSecurityLevel;
|
||||
const difficulty = calculateDifficulty(startingSecurityLevel);
|
||||
const reward = calculateReward(startingSecurityLevel);
|
||||
const maxLevel = location.infiltrationData.maxClearanceLevel;
|
||||
return {
|
||||
location: {
|
||||
city: location.city!,
|
||||
city: locationCity,
|
||||
name: location.name,
|
||||
},
|
||||
reward: {
|
||||
|
@ -47,7 +47,7 @@ export function portHandle(n: PortNumber): NetscriptPort {
|
||||
};
|
||||
}
|
||||
|
||||
export function writePort(n: PortNumber, value: unknown): any {
|
||||
export function writePort(n: PortNumber, value: unknown): unknown {
|
||||
const port = getPort(n);
|
||||
// Primitives don't need to be cloned.
|
||||
port.add(isObjectLike(value) ? structuredClone(value) : value);
|
||||
@ -63,15 +63,15 @@ export function tryWritePort(n: PortNumber, value: unknown): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function readPort(n: PortNumber): any {
|
||||
export function readPort(n: PortNumber): unknown {
|
||||
const port = NetscriptPorts.get(n);
|
||||
if (!port || !port.data.length) return emptyPortData;
|
||||
const returnVal = port.data.shift();
|
||||
const returnVal: unknown = port.data.shift();
|
||||
if (!port.data.length && !port.resolver) NetscriptPorts.delete(n);
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
export function peekPort(n: PortNumber): any {
|
||||
export function peekPort(n: PortNumber): unknown {
|
||||
const port = NetscriptPorts.get(n);
|
||||
if (!port || !port.data.length) return emptyPortData;
|
||||
// Needed to avoid exposing internal objects.
|
||||
|
@ -26,6 +26,7 @@ import { isSleeveFactionWork } from "../Work/SleeveFactionWork";
|
||||
import { isSleeveCompanyWork } from "../Work/SleeveCompanyWork";
|
||||
import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork";
|
||||
import { canAccessBitNodeFeature } from "../../../BitNode/BitNodeUtils";
|
||||
import { getKeyFromReactElements } from "../../../utils/StringHelperFunctions";
|
||||
|
||||
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
|
||||
|
||||
@ -177,7 +178,7 @@ export function EarningsElement(props: IProps): React.ReactElement {
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{data.map(([a, b]) => (
|
||||
<TableRow key={a.toString() + b.toString()}>
|
||||
<TableRow key={getKeyFromReactElements(a, b)}>
|
||||
<TableCell classes={{ root: classes.cellNone }}>
|
||||
<Typography>{a}</Typography>
|
||||
</TableCell>
|
||||
|
@ -231,16 +231,16 @@ function parseOnlyRamCalculate(
|
||||
prefix: string,
|
||||
obj: object,
|
||||
ref: string,
|
||||
): { func: () => number | number; refDetail: string } | undefined => {
|
||||
): { func: (() => number) | number; refDetail: string } | undefined => {
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
const elem = Object.entries(obj).find(([key]) => key === ref);
|
||||
if (elem !== undefined && (typeof elem[1] === "function" || typeof elem[1] === "number")) {
|
||||
return { func: elem[1], refDetail: `${prefix}${ref}` };
|
||||
return { func: elem[1] as (() => number) | number, refDetail: `${prefix}${ref}` };
|
||||
}
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
const found = findFunc(`${key}.`, value, ref);
|
||||
const found = findFunc(`${key}.`, value as object, ref);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ export class Script implements ContentFile {
|
||||
const ramCalc = calculateRamUsage(this.code, this.filename, this.server, otherScripts);
|
||||
if (ramCalc.cost && ramCalc.cost >= RamCostConstants.Base) {
|
||||
this.ramUsage = roundToTwo(ramCalc.cost);
|
||||
this.ramUsageEntries = ramCalc.entries as RamUsageEntry[];
|
||||
this.ramUsageEntries = ramCalc.entries;
|
||||
this.ramCalculationError = null;
|
||||
return;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
// @ts-expect-error This library does not have types.
|
||||
import * as MonacoVim from "monaco-vim";
|
||||
import type { editor } from "monaco-editor";
|
||||
type IStandaloneCodeEditor = editor.IStandaloneCodeEditor;
|
||||
@ -18,8 +17,7 @@ interface IProps {
|
||||
}
|
||||
|
||||
export function useVimEditor({ editor, vim, onOpenNextTab, onOpenPreviousTab, onSave }: IProps) {
|
||||
// monaco-vim does not have types, so this is an any
|
||||
const [vimEditor, setVimEditor] = useState<any>(null);
|
||||
const [vimEditor, setVimEditor] = useState<ReturnType<typeof MonacoVim.initVimMode> | null>(null);
|
||||
|
||||
const statusBarRef = useRef<React.ReactElement | null>(null);
|
||||
const rerender = useRerender();
|
||||
@ -30,7 +28,6 @@ export function useVimEditor({ editor, vim, onOpenNextTab, onOpenPreviousTab, on
|
||||
useEffect(() => {
|
||||
// setup monaco-vim
|
||||
if (vim && editor && !vimEditor) {
|
||||
// Using try/catch because MonacoVim does not have types.
|
||||
try {
|
||||
setVimEditor(MonacoVim.initVimMode(editor, statusBarRef, StatusBar, rerender));
|
||||
MonacoVim.VimMode.Vim.defineEx("write", "w", function () {
|
||||
@ -65,8 +62,7 @@ export function useVimEditor({ editor, vim, onOpenNextTab, onOpenPreviousTab, on
|
||||
MonacoVim.VimMode.Vim.mapCommand("gT", "action", "prevTabs", {}, { context: "normal" });
|
||||
editor.focus();
|
||||
} catch (e) {
|
||||
console.error("An error occurred while loading monaco-vim:");
|
||||
console.error(e);
|
||||
console.error("An error occurred while loading monaco-vim:", e);
|
||||
}
|
||||
} else if (!vim) {
|
||||
// When vim mode is disabled
|
||||
|
@ -2,6 +2,7 @@ import { GetServer } from "../../Server/AllServers";
|
||||
import { editor, Uri } from "monaco-editor";
|
||||
import { OpenScript } from "./OpenScript";
|
||||
import { getFileType, FileType } from "../../utils/ScriptTransformer";
|
||||
import { throwIfReachable } from "../../utils/helpers/throwIfReachable";
|
||||
|
||||
function getServerCode(scripts: OpenScript[], index: number): string | null {
|
||||
const openScript = scripts[index];
|
||||
@ -48,7 +49,7 @@ function makeModel(hostname: string, filename: string, code: string) {
|
||||
language = "javascript";
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Invalid file type: ${fileType}. Filename: ${filename}.`);
|
||||
throwIfReachable(fileType);
|
||||
}
|
||||
//if somehow a model already exist return it
|
||||
return editor.getModel(uri) ?? editor.createModel(code, language, uri);
|
||||
|
@ -8,8 +8,9 @@ import Typography from "@mui/material/Typography";
|
||||
import ExpandLessIcon from "@mui/icons-material/ExpandLess";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
|
||||
import { SidebarItem, ICreateProps as IItemProps } from "./SidebarItem";
|
||||
import { SidebarItem, ICreateProps as IItemProps, type SidebarItemProps } from "./SidebarItem";
|
||||
import type { Page } from "../../ui/Router";
|
||||
import type { PartialRecord } from "../../Types/Record";
|
||||
|
||||
type SidebarAccordionProps = {
|
||||
key_: string;
|
||||
@ -19,9 +20,12 @@ type SidebarAccordionProps = {
|
||||
items: (IItemProps | boolean)[];
|
||||
icon: React.ReactElement["type"];
|
||||
sidebarOpen: boolean;
|
||||
classes: any;
|
||||
classes: Record<"listitem" | "active", string>;
|
||||
};
|
||||
|
||||
type ClickFnCacheKeyType = (page: Page) => void;
|
||||
type ClickFnCacheValueType = PartialRecord<Page, SidebarItemProps["clickFn"]>;
|
||||
|
||||
// We can't useCallback for this, because in the items map it would be
|
||||
// called a changing number of times, and hooks can't be called in loops. So
|
||||
// we set up this explicit cache of function objects instead.
|
||||
@ -30,7 +34,7 @@ type SidebarAccordionProps = {
|
||||
// WeakMap prevents memory leaks. We won't drop slices of the cache too soon,
|
||||
// because the fn keys are themselves memoized elsewhere, which keeps them
|
||||
// alive and thus keeps the WeakMap entries alive.
|
||||
const clickFnCache = new WeakMap();
|
||||
const clickFnCache = new WeakMap<ClickFnCacheKeyType, ClickFnCacheValueType>();
|
||||
function getClickFn(toWrap: (page: Page) => void, page: Page) {
|
||||
let first = clickFnCache.get(toWrap);
|
||||
if (first === undefined) {
|
||||
|
@ -18,7 +18,7 @@ export interface ICreateProps {
|
||||
export interface SidebarItemProps extends ICreateProps {
|
||||
clickFn: () => void;
|
||||
flash: boolean;
|
||||
classes: any;
|
||||
classes: Record<"listitem" | "active", string>;
|
||||
sidebarOpen: boolean;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
|
||||
import * as React from "react";
|
||||
import { throwIfReachable } from "../utils/helpers/throwIfReachable";
|
||||
|
||||
export interface IProcessOrderRefs {
|
||||
stockMarket: IStockMarket;
|
||||
@ -50,8 +51,8 @@ export function processOrders(
|
||||
return; // Newly created, so no orders to process
|
||||
}
|
||||
let stockOrders = orderBook[stock.symbol];
|
||||
if (stockOrders == null || !(stockOrders.constructor === Array)) {
|
||||
console.error(`Invalid Order book for ${stock.symbol} in processOrders(): ${stockOrders}`);
|
||||
if (stockOrders == null || !Array.isArray(stockOrders)) {
|
||||
console.error(`Invalid Order book for ${stock.symbol} in processOrders(). stockOrders: ${stockOrders}`);
|
||||
stockOrders = [];
|
||||
return;
|
||||
}
|
||||
@ -88,8 +89,7 @@ export function processOrders(
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.warn(`Invalid order type: ${order.type}`);
|
||||
return;
|
||||
throwIfReachable(order.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,8 +137,7 @@ function executeOrder(order: Order, refs: IProcessOrderRefs): void {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.warn(`Invalid order type: ${order.type}`);
|
||||
return;
|
||||
throwIfReachable(order.type);
|
||||
}
|
||||
|
||||
// Position type, for logging/message purposes
|
||||
|
@ -21,6 +21,9 @@ export function check(args: (string | number | boolean)[], server: BaseServer):
|
||||
Terminal.error(`No script named ${scriptName} is running on the server`);
|
||||
return;
|
||||
}
|
||||
runningScripts.values().next().value.displayLog();
|
||||
const next = runningScripts.values().next();
|
||||
if (!next.done) {
|
||||
next.value.displayLog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,11 +9,11 @@ export function expr(args: (string | number | boolean)[]): void {
|
||||
|
||||
// Sanitize the math expression
|
||||
const sanitizedExpr = expr.replace(/[^-()\d/*+.%]/g, "");
|
||||
let result;
|
||||
let result: string;
|
||||
try {
|
||||
result = eval?.(sanitizedExpr);
|
||||
result = String(eval?.(sanitizedExpr));
|
||||
} catch (e) {
|
||||
Terminal.error(`Could not evaluate expression: ${sanitizedExpr}`);
|
||||
Terminal.error(`Could not evaluate expression: ${sanitizedExpr}. Error: ${e}.`);
|
||||
return;
|
||||
}
|
||||
Terminal.print(result);
|
||||
|
@ -86,7 +86,7 @@ export function TerminalInput(): React.ReactElement {
|
||||
function getSearchSuggestionPrespace() {
|
||||
const currentPrefix = `[${Player.getCurrentServer().hostname} /${Terminal.cwd()}]> `;
|
||||
const prefixLength = `${currentPrefix}${value}`.length;
|
||||
return Array(prefixLength).fill(" ");
|
||||
return Array<string>(prefixLength).fill(" ");
|
||||
}
|
||||
|
||||
function modifyInput(mod: Modification): void {
|
||||
@ -206,7 +206,7 @@ export function TerminalInput(): React.ReactElement {
|
||||
return () => document.removeEventListener("keydown", keyDown);
|
||||
});
|
||||
|
||||
async function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): Promise<void> {
|
||||
async function onKeyDown(event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>): Promise<void> {
|
||||
const ref = terminalInput.current;
|
||||
|
||||
// Run command or insert newline
|
||||
@ -427,7 +427,11 @@ export function TerminalInput(): React.ReactElement {
|
||||
setPossibilities([]);
|
||||
resetSearch();
|
||||
},
|
||||
onKeyDown: onKeyDown,
|
||||
onKeyDown: (event) => {
|
||||
onKeyDown(event).catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
},
|
||||
}}
|
||||
></TextField>
|
||||
<Popper
|
||||
|
@ -41,7 +41,7 @@ export function TerminalRoot(): React.ReactElement {
|
||||
const [key, setKey] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const debounced = _.debounce(async () => rerender(), 25, { maxWait: 50 });
|
||||
const debounced = _.debounce(() => rerender(), 25, { maxWait: 50 });
|
||||
const unsubscribe = TerminalEvents.subscribe(debounced);
|
||||
return () => {
|
||||
debounced.cancel();
|
||||
@ -51,7 +51,7 @@ export function TerminalRoot(): React.ReactElement {
|
||||
|
||||
useEffect(() => {
|
||||
const clear = () => setKey((key) => key + 1);
|
||||
const debounced = _.debounce(async () => clear(), 25, { maxWait: 50 });
|
||||
const debounced = _.debounce(() => clear(), 25, { maxWait: 50 });
|
||||
const unsubscribe = TerminalClearEvents.subscribe(debounced);
|
||||
return () => {
|
||||
debounced.cancel();
|
||||
|
@ -917,7 +917,7 @@ export const codingContractTypesMetadata: CodingContractType<any>[] = [
|
||||
desc: (data: number[][]): string => {
|
||||
return [
|
||||
"You are located in the top-left corner of the following grid:\n\n",
|
||||
` [${data.map((line) => "[" + line + "]").join(",\n ")}]\n\n`,
|
||||
` [${data.map((line) => `[${line}]`).join(",\n ")}]\n\n`,
|
||||
"You are trying to find the shortest path to the bottom-right corner of the grid,",
|
||||
"but there are obstacles on the grid that you cannot move onto.",
|
||||
"These obstacles are denoted by '1', while empty spaces are denoted by 0.\n\n",
|
||||
@ -945,8 +945,8 @@ export const codingContractTypesMetadata: CodingContractType<any>[] = [
|
||||
const dstX = width - 1;
|
||||
const minPathLength = dstY + dstX; // Math.abs(dstY - srcY) + Math.abs(dstX - srcX)
|
||||
|
||||
const grid: number[][] = new Array(height);
|
||||
for (let y = 0; y < height; y++) grid[y] = new Array(width).fill(0);
|
||||
const grid: number[][] = new Array<number[]>(height);
|
||||
for (let y = 0; y < height; y++) grid[y] = new Array<number>(width).fill(0);
|
||||
|
||||
for (let y = 0; y < height; y++) {
|
||||
for (let x = 0; x < width; x++) {
|
||||
@ -969,12 +969,12 @@ export const codingContractTypesMetadata: CodingContractType<any>[] = [
|
||||
const dstY = height - 1;
|
||||
const dstX = width - 1;
|
||||
|
||||
const distance: [number][] = new Array(height);
|
||||
const distance: number[][] = new Array<number[]>(height);
|
||||
//const prev: [[number, number] | undefined][] = new Array(height);
|
||||
const queue: [number, number][] = [];
|
||||
|
||||
for (let y = 0; y < height; y++) {
|
||||
distance[y] = new Array(width).fill(Infinity) as [number];
|
||||
distance[y] = new Array<number>(width).fill(Infinity);
|
||||
//prev[y] = new Array(width).fill(undefined) as [undefined];
|
||||
}
|
||||
|
||||
@ -1422,7 +1422,7 @@ export const codingContractTypesMetadata: CodingContractType<any>[] = [
|
||||
//Attempt to construct one to check if this is correct.
|
||||
if (sanitizedPlayerAns === "") {
|
||||
//Verify that there is no solution by attempting to create a proper 2-coloring.
|
||||
const coloring: (number | undefined)[] = Array(data[0]).fill(undefined);
|
||||
const coloring: (number | undefined)[] = Array<number | undefined>(data[0]).fill(undefined);
|
||||
while (coloring.some((val) => val === undefined)) {
|
||||
//Color a vertex in the graph
|
||||
const initialVertex: number = coloring.findIndex((val) => val === undefined);
|
||||
@ -1435,9 +1435,7 @@ export const codingContractTypesMetadata: CodingContractType<any>[] = [
|
||||
const neighbors: number[] = neighbourhood(v);
|
||||
|
||||
//For each vertex u adjacent to v
|
||||
for (const id in neighbors) {
|
||||
const u: number = neighbors[id];
|
||||
|
||||
for (const u of neighbors) {
|
||||
//Set the color of u to the opposite of v's color if it is new,
|
||||
//then add u to the frontier to continue the algorithm.
|
||||
if (coloring[u] === undefined) {
|
||||
|
@ -46,7 +46,7 @@ export const A = (props: React.PropsWithChildren<{ href?: string }>): React.Reac
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
<CorruptableText content={props.children + ""} spoiler={true} />
|
||||
<CorruptableText content={String(props.children)} spoiler={true} />
|
||||
</span>
|
||||
);
|
||||
return (
|
||||
|
@ -38,7 +38,7 @@ type RowName = SkillRowName | "HP" | "Money";
|
||||
const OverviewEventEmitter = new EventEmitter();
|
||||
|
||||
// These values aren't displayed, they're just used for comparison to check if state has changed
|
||||
const valUpdaters: Record<RowName, () => any> = {
|
||||
const valUpdaters: Record<RowName, () => unknown> = {
|
||||
HP: () => Player.hp.current + "|" + Player.hp.max, // This isn't displayed, it's just compared for updates.
|
||||
Money: () => Player.money,
|
||||
Hack: () => Player.skills.hacking,
|
||||
|
@ -26,9 +26,11 @@ export function CinematicLine(props: IProps): React.ReactElement {
|
||||
return;
|
||||
}
|
||||
let cancel = false;
|
||||
(async () => {
|
||||
await sleep(10).then(() => !cancel && advance());
|
||||
})();
|
||||
sleep(10)
|
||||
.then(() => !cancel && advance())
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
return () => {
|
||||
cancel = true;
|
||||
};
|
||||
|
@ -399,7 +399,11 @@ export const ImportSave = (props: { saveData: SaveData; automatic: boolean }): J
|
||||
<ConfirmationModal
|
||||
open={isImportModalOpen}
|
||||
onClose={closeImportModal}
|
||||
onConfirm={handleImport}
|
||||
onConfirm={() => {
|
||||
handleImport().catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
}}
|
||||
confirmationText={
|
||||
<>
|
||||
Importing new save game data will <strong>completely wipe</strong> the current game data!
|
||||
|
@ -298,7 +298,16 @@ function LogWindow({ hidden, script, onClose }: LogWindowProps): React.ReactElem
|
||||
return !(bounds.right < 0 || bounds.bottom < 0 || bounds.left > innerWidth || bounds.top > outerWidth);
|
||||
};
|
||||
|
||||
const onDrag = (e: DraggableEvent): void | false => {
|
||||
/**
|
||||
* The returned type of onDrag is a bit weird here. The Draggable component expects an onDrag that returns "void | false".
|
||||
* In that component's internal code, it checks for the explicit "false" value. If onDrag returns false, the component
|
||||
* cancels the dragging.
|
||||
*
|
||||
* That's why they use "void | false" as the returned type. However, in TypeScript, "void" is not supposed to be used
|
||||
* like that. ESLint will complain "void is not valid as a constituent in a union type". Please check its documentation
|
||||
* for the reason. In order to solve this problem, I changed the returned type to "undefined | false".
|
||||
*/
|
||||
const onDrag = (e: DraggableEvent): undefined | false => {
|
||||
e.preventDefault();
|
||||
// bound to body
|
||||
if (
|
||||
|
@ -98,7 +98,7 @@ export function RecoveryRoot({ softReset, errorData, resetError }: IProps): Reac
|
||||
{sourceError && (
|
||||
<Box>
|
||||
<Typography variant="h6" color={Settings.theme.error}>
|
||||
Error: {sourceError.toString()}
|
||||
Error: {String(sourceError)}
|
||||
</Typography>
|
||||
<br />
|
||||
</Box>
|
||||
|
@ -14,7 +14,7 @@ interface IProps {
|
||||
const useStyles = makeStyles()({
|
||||
snackbar: {
|
||||
// Log popup z-index increments, so let's add a padding to be well above them.
|
||||
zIndex: `${logBoxBaseZIndex + 1000} !important` as any,
|
||||
zIndex: `${logBoxBaseZIndex + 1000} !important`,
|
||||
|
||||
"& .MuiAlert-icon": {
|
||||
alignSelf: "center",
|
||||
|
@ -1,4 +1,4 @@
|
||||
// choose random character for generating plaintexts to compress
|
||||
// choose random characters for generating plaintext to compress
|
||||
export function comprGenChar(): string {
|
||||
const r = Math.random();
|
||||
if (r < 0.4) {
|
||||
@ -34,13 +34,13 @@ export function comprLZGenerate(): string {
|
||||
return plain.substring(0, length);
|
||||
}
|
||||
|
||||
// compress plaintest string
|
||||
// compress plaintext string
|
||||
export function comprLZEncode(plain: string): string {
|
||||
// for state[i][j]:
|
||||
// if i is 0, we're adding a literal of length j
|
||||
// else, we're adding a backreference of offset i and length j
|
||||
let cur_state: (string | null)[][] = Array.from(Array(10), () => Array(10).fill(null));
|
||||
let new_state: (string | null)[][] = Array.from(Array(10), () => Array(10));
|
||||
let cur_state: (string | null)[][] = Array.from(Array(10), () => Array<string | null>(10).fill(null));
|
||||
let new_state: (string | null)[][] = Array.from(Array(10), () => Array<string | null>(10));
|
||||
|
||||
function set(state: (string | null)[][], i: number, j: number, str: string): void {
|
||||
const current = state[i][j];
|
||||
|
@ -3,7 +3,7 @@ import { Terminal } from "../Terminal";
|
||||
const deprecatedWarningsGiven = new Set();
|
||||
export function setDeprecatedProperties(
|
||||
obj: object,
|
||||
properties: Record<string, { identifier: string; message: string; value: any }>,
|
||||
properties: Record<string, { identifier: string; message: string; value: unknown }>,
|
||||
) {
|
||||
for (const [name, info] of Object.entries(properties)) {
|
||||
Object.defineProperty(obj, name, {
|
||||
@ -11,7 +11,7 @@ export function setDeprecatedProperties(
|
||||
deprecationWarning(info.identifier, info.message);
|
||||
return info.value;
|
||||
},
|
||||
set: (value: any) => (info.value = value),
|
||||
set: (value: unknown) => (info.value = value),
|
||||
enumerable: true,
|
||||
});
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import * as allEnums from "../Enums";
|
||||
import { assertString } from "../Netscript/TypeAssertion";
|
||||
import { errorMessage } from "../Netscript/ErrorMessages";
|
||||
import { getRandomIntInclusive } from "./helpers/getRandomIntInclusive";
|
||||
import { getRecordValues } from "../Types/Record";
|
||||
|
||||
interface GetMemberOptions {
|
||||
/** Whether to use fuzzy matching on the input (case insensitive, ignore spaces and dashes) */
|
||||
@ -22,7 +23,7 @@ class EnumHelper<EnumObj extends object, EnumMember extends Member<EnumObj> & st
|
||||
constructor(obj: EnumObj, name: string) {
|
||||
this.name = name;
|
||||
this.defaultArgName = name.charAt(0).toLowerCase() + name.slice(1);
|
||||
this.valueArray = Object.values(obj);
|
||||
this.valueArray = getRecordValues(obj);
|
||||
this.valueSet = new Set(this.valueArray);
|
||||
this.fuzzMap = new Map(this.valueArray.map((val) => [val.toLowerCase().replace(/[ -]+/g, ""), val]));
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
export function HammingEncode(data: number): string {
|
||||
const enc: number[] = [0];
|
||||
const data_bits: any[] = data.toString(2).split("").reverse();
|
||||
|
||||
data_bits.forEach((e, i, a) => {
|
||||
a[i] = parseInt(e);
|
||||
});
|
||||
const data_bits: number[] = data
|
||||
.toString(2)
|
||||
.split("")
|
||||
.reverse()
|
||||
.map((value) => parseInt(value));
|
||||
|
||||
let k = data_bits.length;
|
||||
|
||||
@ -18,35 +18,36 @@ export function HammingEncode(data: number): string {
|
||||
}
|
||||
}
|
||||
|
||||
let parity: any = 0;
|
||||
let parityNumber = 0;
|
||||
|
||||
/* Figure out the subsection parities */
|
||||
for (let i = 0; i < enc.length; i++) {
|
||||
if (enc[i]) {
|
||||
parity ^= i;
|
||||
parityNumber ^= i;
|
||||
}
|
||||
}
|
||||
|
||||
parity = parity.toString(2).split("").reverse();
|
||||
parity.forEach((e: any, i: any, a: any) => {
|
||||
a[i] = parseInt(e);
|
||||
});
|
||||
const parityArray = parityNumber
|
||||
.toString(2)
|
||||
.split("")
|
||||
.reverse()
|
||||
.map((value) => parseInt(value));
|
||||
|
||||
/* Set the parity bits accordingly */
|
||||
for (let i = 0; i < parity.length; i++) {
|
||||
enc[2 ** i] = parity[i] ? 1 : 0;
|
||||
for (let i = 0; i < parityArray.length; i++) {
|
||||
enc[2 ** i] = parityArray[i] ? 1 : 0;
|
||||
}
|
||||
|
||||
parity = 0;
|
||||
parityNumber = 0;
|
||||
/* Figure out the overall parity for the entire block */
|
||||
for (let i = 0; i < enc.length; i++) {
|
||||
if (enc[i]) {
|
||||
parity++;
|
||||
parityNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally set the overall parity bit */
|
||||
enc[0] = parity % 2 == 0 ? 0 : 1;
|
||||
enc[0] = parityNumber % 2 == 0 ? 0 : 1;
|
||||
|
||||
return enc.join("");
|
||||
}
|
||||
@ -68,11 +69,11 @@ export function HammingEncodeProperly(data: number): string {
|
||||
const k: number = 2 ** m - m - 1;
|
||||
|
||||
const enc: number[] = [0];
|
||||
const data_bits: any[] = data.toString(2).split("").reverse();
|
||||
|
||||
data_bits.forEach((e, i, a) => {
|
||||
a[i] = parseInt(e);
|
||||
});
|
||||
const data_bits: number[] = data
|
||||
.toString(2)
|
||||
.split("")
|
||||
.reverse()
|
||||
.map((value) => parseInt(value));
|
||||
|
||||
/* Flip endianness as in the original implementation by Hedrauta
|
||||
* and write the data back to front
|
||||
@ -83,35 +84,36 @@ export function HammingEncodeProperly(data: number): string {
|
||||
}
|
||||
}
|
||||
|
||||
let parity: any = 0;
|
||||
let parityNumber = 0;
|
||||
|
||||
/* Figure out the subsection parities */
|
||||
for (let i = 0; i < n; i++) {
|
||||
if (enc[i]) {
|
||||
parity ^= i;
|
||||
parityNumber ^= i;
|
||||
}
|
||||
}
|
||||
|
||||
parity = parity.toString(2).split("").reverse();
|
||||
parity.forEach((e: any, i: any, a: any) => {
|
||||
a[i] = parseInt(e);
|
||||
});
|
||||
const parityArray = parityNumber
|
||||
.toString(2)
|
||||
.split("")
|
||||
.reverse()
|
||||
.map((value) => parseInt(value));
|
||||
|
||||
/* Set the parity bits accordingly */
|
||||
for (let i = 0; i < m; i++) {
|
||||
enc[2 ** i] = parity[i] ? 1 : 0;
|
||||
enc[2 ** i] = parityArray[i] ? 1 : 0;
|
||||
}
|
||||
|
||||
parity = 0;
|
||||
parityNumber = 0;
|
||||
/* Figure out the overall parity for the entire block */
|
||||
for (let i = 0; i < n; i++) {
|
||||
if (enc[i]) {
|
||||
parity++;
|
||||
parityNumber++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally set the overall parity bit */
|
||||
enc[0] = parity % 2 == 0 ? 0 : 1;
|
||||
enc[0] = parityNumber % 2 == 0 ? 0 : 1;
|
||||
|
||||
return enc.join("");
|
||||
}
|
||||
@ -121,8 +123,9 @@ export function HammingDecode(data: string): number {
|
||||
const bits: number[] = [];
|
||||
|
||||
/* TODO why not just work with an array of digits from the start? */
|
||||
for (const i in data.split("")) {
|
||||
const bit = parseInt(data[i]);
|
||||
const bitStringArray = data.split("");
|
||||
for (let i = 0; i < bitStringArray.length; ++i) {
|
||||
const bit = parseInt(bitStringArray[i]);
|
||||
bits[i] = bit;
|
||||
|
||||
if (bit) {
|
||||
|
@ -125,3 +125,9 @@ export function getNsApiDocumentationUrl(isDevBranch: boolean = CONSTANTS.isDevB
|
||||
isDevBranch ? "dev" : "stable"
|
||||
}/markdown/bitburner.ns.md`;
|
||||
}
|
||||
|
||||
export function getKeyFromReactElements(a: string | React.JSX.Element, b: string | React.JSX.Element): string {
|
||||
const keyOfA = typeof a === "string" ? a : a.key ?? "";
|
||||
const keyOfb = typeof b === "string" ? b : b.key ?? "";
|
||||
return keyOfA + keyOfb;
|
||||
}
|
||||
|
3
src/utils/helpers/throwIfReachable.ts
Normal file
3
src/utils/helpers/throwIfReachable.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export function throwIfReachable(missingCase: never) {
|
||||
throw new Error(`The case of ${missingCase} was not handled.`);
|
||||
}
|
Loading…
Reference in New Issue
Block a user