Merge branch 'dev' into eslint

This commit is contained in:
Steven Evans 2018-06-27 23:42:42 -04:00 committed by GitHub
commit 8624fff015
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 28191 additions and 28107 deletions

56102
dist/engine.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -92,9 +92,9 @@ function initBitNodes() {
"in the game. <br><br>" + "in the game. <br><br>" +
"In addition, this Source-File will unlock the getBitNodeMultipliers() Netscript function, " + "In addition, this Source-File will unlock the getBitNodeMultipliers() Netscript function, " +
"and will also raise all of your hacking-related multipliers by:<br><br>" + "and will also raise all of your hacking-related multipliers by:<br><br>" +
"Level 1: 4%<br>" + "Level 1: 8%<br>" +
"Level 2: 6%<br>" + "Level 2: 12%<br>" +
"Level 3: 7%"); "Level 3: 14%");
BitNodes["BitNode6"] = new BitNode(6, "Bladeburners", "Like Tears in Rain", BitNodes["BitNode6"] = new BitNode(6, "Bladeburners", "Like Tears in Rain",
"In the middle of the 21st century, OmniTek Incorporated began designing and manufacturing advanced synthetic " + "In the middle of the 21st century, OmniTek Incorporated began designing and manufacturing advanced synthetic " +
"androids, or Synthoids for short. They achieved a major technological breakthrough in the sixth generation " + "androids, or Synthoids for short. They achieved a major technological breakthrough in the sixth generation " +
@ -123,7 +123,7 @@ function initBitNodes() {
"and more intelligent than the humans that had created them.<br><br>" + "and more intelligent than the humans that had created them.<br><br>" +
"In this BitNode you will be able to access the Bladeburner API, which allows you to access Bladeburner " + "In this BitNode you will be able to access the Bladeburner API, which allows you to access Bladeburner " +
"functionality through Netscript. Furthermore: <br><br>" + "functionality through Netscript. Furthermore: <br><br>" +
"The rank you gain from Bladeburner contracts/operations is reduced by 50%<br>" + "The rank you gain from Bladeburner contracts/operations is reduced by 40%<br>" +
"Bladeburner skills cost twice as many skill points<br>" + "Bladeburner skills cost twice as many skill points<br>" +
"Augmentations are 3x more expensive<br>" + "Augmentations are 3x more expensive<br>" +
"Hacking and Hacknet Nodes will be significantly less profitable<br>" + "Hacking and Hacknet Nodes will be significantly less profitable<br>" +
@ -152,7 +152,7 @@ function initBitNodes() {
"Level 2: Ability to short stocks in other BitNodes<br>" + "Level 2: Ability to short stocks in other BitNodes<br>" +
"Level 3: Ability to use limit/stop orders in other BitNodes<br><br>" + "Level 3: Ability to use limit/stop orders in other BitNodes<br><br>" +
"This Source-File also increases your hacking growth multipliers by: " + "This Source-File also increases your hacking growth multipliers by: " +
"<br>Level 1: 8%<br>Level 2: 12%<br>Level 3: 14%"); "<br>Level 1: 12%<br>Level 2: 18%<br>Level 3: 21%");
BitNodes["BitNode9"] = new BitNode(9, "Do Androids Dream?", "COMING SOON"); BitNodes["BitNode9"] = new BitNode(9, "Do Androids Dream?", "COMING SOON");
BitNodes["BitNode10"] = new BitNode(10, "MegaCorp", "COMING SOON"); //Not sure yet BitNodes["BitNode10"] = new BitNode(10, "MegaCorp", "COMING SOON"); //Not sure yet
BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.", BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.",
@ -182,7 +182,8 @@ function initBitNodes() {
"To iterate is human, to recurse divine.<br><br>" + "To iterate is human, to recurse divine.<br><br>" +
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give your Souce-File 12, or " + "Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give your Souce-File 12, or " +
"if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " + "if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " +
"of Source-File 12 will increase all of your multipliers by 1%."); "of Source-File 12 will increase all of your multipliers by 1%. This effect is additive with itself, NOT multiplicative. In other words, " +
"level N of this Source-File will increase all of your multipliers by N%");
//Books: Frontera, Shiner //Books: Frontera, Shiner
BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes
BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON"); BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON");
@ -310,7 +311,7 @@ function initBitNodeMultipliers() {
BitNodeMultipliers.HackExpGain = 0.25; BitNodeMultipliers.HackExpGain = 0.25;
break; break;
case 7: //Bladeburner 2079 case 7: //Bladeburner 2079
BitNodeMultipliers.BladeburnerRank = 0.5; BitNodeMultipliers.BladeburnerRank = 0.6;
BitNodeMultipliers.BladeburnerSkillCost = 2; BitNodeMultipliers.BladeburnerSkillCost = 2;
BitNodeMultipliers.AugmentationMoneyCost = 3; BitNodeMultipliers.AugmentationMoneyCost = 3;
BitNodeMultipliers.HackingLevelMultiplier = 0.5; BitNodeMultipliers.HackingLevelMultiplier = 0.5;

@ -60,7 +60,7 @@ var OperationSuccessesPerLevel = 2.5; //How many successes you need to level up
var RanksPerSkillPoint = 4; //How many ranks needed to get 1 Skill Point var RanksPerSkillPoint = 4; //How many ranks needed to get 1 Skill Point
var ContractBaseMoneyGain = 10e3; //Base Money Gained per contract var ContractBaseMoneyGain = 40e3; //Base Money Gained per contract
//DOM related variables //DOM related variables
var ActiveActionCssClass = "bladeburner-active-action"; var ActiveActionCssClass = "bladeburner-active-action";

@ -490,6 +490,14 @@ let CONSTANTS = {
LatestUpdate: LatestUpdate:
"v0.39.1<br>" + "v0.39.1<br>" +
"* Bladeburner Rank gain in BN-7 is now reduced by 40% instead of 50%<br>" +
"* Quadrupled the amount of money gained from Bladeburner contracts<br>" +
"* Doubled the effects of Source-File 5. Now gives 8%, 12%, and 14% increase to all hacking multipliers " +
"at levels 1, 2, and 3, respectively (increased from 4%/6%, 7%)<br>" +
"* Increased the effect of Source-File 8. It now gives a 12%, 18% and 21% to your hacking growth multiplier " +
"at levels 1, 2, and 3, respectively (increased from 8%, 12%, 14%)<br>" +
"* The effect of Source-File 12 is now additive with itself, rather than multiplicative. This means " +
"that level N of Source-File 12 now increases all multipliers by N%<br>" +
"* The setting to suppress the confirmation box when purchasing Augmentations was moved into the main Options menu (by Github user hydroflame)<br>" "* The setting to suppress the confirmation box when purchasing Augmentations was moved into the main Options menu (by Github user hydroflame)<br>"

@ -95,7 +95,7 @@ const Crimes = {
dexterity_exp: 60, dexterity_exp: 60,
agility_exp: 60, agility_exp: 60,
hacking_skill_success_weight: 0.5, hacking_success_weight: 0.5,
dexterity_success_weight: 1, dexterity_success_weight: 1,
agility_success_weight: 1, agility_success_weight: 1,
@ -117,7 +117,7 @@ const Crimes = {
dexterity_exp: 150, dexterity_exp: 150,
charisma_exp: 15, charisma_exp: 15,
hacking_skill_success_weight: 0.05, hacking_success_weight: 0.05,
dexterity_success_weight: 1.25, dexterity_success_weight: 1.25,
intelligence_exp: 2 * CONSTANTS.IntelligenceCrimeBaseExpGain, intelligence_exp: 2 * CONSTANTS.IntelligenceCrimeBaseExpGain,
@ -158,7 +158,7 @@ const Crimes = {
agility_exp: 80, agility_exp: 80,
charisma_exp: 40, charisma_exp: 40,
hacking_skill_success_weight: 1, hacking_success_weight: 1,
strength_success_weight: 1, strength_success_weight: 1,
dexterity_success_weight: 4, dexterity_success_weight: 4,
agility_success_weight: 2, agility_success_weight: 2,
@ -205,7 +205,7 @@ const Crimes = {
agility_exp: 450, agility_exp: 450,
charisma_exp: 450, charisma_exp: 450,
hacking_skill_success_weight: 1, hacking_success_weight: 1,
strength_success_weight: 1, strength_success_weight: 1,
defense_success_weight: 1, defense_success_weight: 1,
dexterity_success_weight: 1, dexterity_success_weight: 1,

@ -1,12 +1,47 @@
// Contains the "information" property for all the Factions, which is just a description of each faction import { IMap } from "./types";
/**
* Contains the "information" property for all the Factions, which is just a description of each faction
*/
class FactionInfo { class FactionInfo {
/**
* The multiplier to apply to augmentation base purchase price.
*/
augmentationPriceMult: number; augmentationPriceMult: number;
/**
* The multiplier to apply to augmentation reputation base requirement.
*/
augmentationRepRequirementMult: number; augmentationRepRequirementMult: number;
/**
* The names of all other factions considered to be enemies to this faction.
*/
enemies: string[]; enemies: string[];
/**
* The descriptive text to show on the faction's page.
*/
infoText: string; infoText: string;
/**
* A flag indicating if the faction supports field work to earn reputation.
*/
offerFieldWork: boolean; offerFieldWork: boolean;
/**
* A flag indicating if the faction supports hacking missions to earn reputation.
*/
offerHackingMission: boolean; offerHackingMission: boolean;
/**
* A flag indicating if the faction supports hacking work to earn reputation.
*/
offerHackingWork: boolean; offerHackingWork: boolean;
/**
* A flag indicating if the faction supports security work to earn reputation.
*/
offerSecurityWork: boolean; offerSecurityWork: boolean;
constructor(infoText: string, enemies: string[], offerHackingMission: boolean, offerHackingWork: boolean, constructor(infoText: string, enemies: string[], offerHackingMission: boolean, offerHackingWork: boolean,
@ -24,7 +59,11 @@ class FactionInfo {
} }
} }
const FactionInfos = { /**
* A map of all factions and associated info to them.
*/
// tslint:disable-next-line:variable-name
export const FactionInfos: IMap<FactionInfo> = {
// Endgame // Endgame
Illuminati: new FactionInfo("Humanity never changes. No matter how civilized society becomes, it will eventually" + Illuminati: new FactionInfo("Humanity never changes. No matter how civilized society becomes, it will eventually" +
"fall back into chaos. And from this chaos, we are the Invisible hand that guides them to order. ", "fall back into chaos. And from this chaos, we are the Invisible hand that guides them to order. ",
@ -189,5 +228,3 @@ const FactionInfos = {
"Bladeburner contracts/operations will increase your reputation.", "Bladeburner contracts/operations will increase your reputation.",
[], false, false, false, false), [], false, false, false, false),
}; };
export {FactionInfos};

@ -106,7 +106,7 @@ function endInfiltration(inst, success) {
clearEventListeners("infiltration-bribe"); clearEventListeners("infiltration-bribe");
clearEventListeners("infiltration-escape"); clearEventListeners("infiltration-escape");
Engine.loadWorldContent(); Engine.loadLocationContent();
} }
function nextInfiltrationLevel(inst) { function nextInfiltrationLevel(inst) {

@ -43,21 +43,25 @@ function initSourceFiles() {
"know when you gain experience and how much). Higher Intelligence levels will boost your production " + "know when you gain experience and how much). Higher Intelligence levels will boost your production " +
"for many actions in the game. In addition, this Source-File will unlock the getBitNodeMultipliers() " + "for many actions in the game. In addition, this Source-File will unlock the getBitNodeMultipliers() " +
"Netscript function, and will raise all of your hacking-related multipliers by:<br><br> " + "Netscript function, and will raise all of your hacking-related multipliers by:<br><br> " +
"Level 1: 4%<br>" + "Level 1: 8%<br>" +
"Level 2: 6%<br>" + "Level 2: 12%<br>" +
"Level 3: 7%"); "Level 3: 14%");
SourceFiles["SourceFile6"] = new SourceFile(6, "This Source-File allows you to access the NSA's Bladeburner Division in other " + SourceFiles["SourceFile6"] = new SourceFile(6, "This Source-File allows you to access the NSA's Bladeburner Division in other " +
"BitNodes. In addition, this Source-File will raise the experience gain rate of all your combat stats by:<br><br>" + "BitNodes. In addition, this Source-File will raise the experience gain rate of all your combat stats by:<br><br>" +
"Level 1: 8%<br>" + "Level 1: 8%<br>" +
"Level 2: 12%<br>" + "Level 2: 12%<br>" +
"Level 3: 14%"); "Level 3: 14%");
SourceFiles["SourceFile7"] = new SourceFile(7); SourceFiles["SourceFile7"] = new SourceFile(7, "This Source-File allows you to access the Bladeburner Netscript API in other " +
"BitNodes. In addition, this Source-File will increase all of your Bladeburner multipliers by:<br><br>" +
"Level 1: 8%<br>" +
"Level 2: 12%<br>" +
"Level 3: 14%");
SourceFiles["SourceFile8"] = new SourceFile(8, "This Source-File grants the following benefits:<br><br>" + SourceFiles["SourceFile8"] = new SourceFile(8, "This Source-File grants the following benefits:<br><br>" +
"Level 1: Permanent access to WSE and TIX API<br>" + "Level 1: Permanent access to WSE and TIX API<br>" +
"Level 2: Ability to short stocks in other BitNodes<br>" + "Level 2: Ability to short stocks in other BitNodes<br>" +
"Level 3: Ability to use limit/stop orders in other BitNodes<br><br>" + "Level 3: Ability to use limit/stop orders in other BitNodes<br><br>" +
"This Source-File also increases your hacking growth multipliers by: " + "This Source-File also increases your hacking growth multipliers by: " +
"<br>Level 1: 8%<br>Level 2: 12%<br>Level 3: 14%"); "<br>Level 1: 12%<br>Level 2: 18%<br>Level 3: 21%");
SourceFiles["SourceFile9"] = new SourceFile(9); SourceFiles["SourceFile9"] = new SourceFile(9);
SourceFiles["SourceFile10"] = new SourceFile(10); SourceFiles["SourceFile10"] = new SourceFile(10);
SourceFiles["SourceFile11"] = new SourceFile(11, "This Source-File makes it so that company favor increases BOTH the player's salary and reputation gain rate " + SourceFiles["SourceFile11"] = new SourceFile(11, "This Source-File makes it so that company favor increases BOTH the player's salary and reputation gain rate " +
@ -66,7 +70,8 @@ function initSourceFiles() {
"Level 1: 24%<br>" + "Level 1: 24%<br>" +
"Level 2: 36%<br>" + "Level 2: 36%<br>" +
"Level 3: 42%<br>"); "Level 3: 42%<br>");
SourceFiles["SourceFile12"] = new SourceFile(12, "This Source-File increases all your multipliers by 1% per level"); SourceFiles["SourceFile12"] = new SourceFile(12, "This Source-File increases all your multipliers by 1% per level. This effect is additive with itself, " +
"NOT multiplicative. In other words, level N of this Source-File will increase all of your multipliers by N%");
} }
function PlayerOwnedSourceFile(number, level) { function PlayerOwnedSourceFile(number, level) {
@ -143,7 +148,7 @@ function applySourceFile(srcFile) {
case 5: //Artificial Intelligence case 5: //Artificial Intelligence
var mult = 0; var mult = 0;
for (var i = 0; i < srcFile.lvl; ++i) { for (var i = 0; i < srcFile.lvl; ++i) {
mult += (4 / (Math.pow(2, i))); mult += (8 / (Math.pow(2, i)));
} }
var incMult = 1 + (mult / 100); var incMult = 1 + (mult / 100);
Player.hacking_chance_mult *= incMult; Player.hacking_chance_mult *= incMult;
@ -178,7 +183,7 @@ function applySourceFile(srcFile) {
case 8: //Ghost of Wall Street case 8: //Ghost of Wall Street
var mult = 0; var mult = 0;
for (var i = 0; i < srcFile.lvl; ++i) { for (var i = 0; i < srcFile.lvl; ++i) {
mult += (8 / (Math.pow(2, i))); mult += (12 / (Math.pow(2, i)));
} }
var incMult = 1 + (mult / 100); var incMult = 1 + (mult / 100);
Player.hacking_grow_mult *= incMult; Player.hacking_grow_mult *= incMult;
@ -193,8 +198,8 @@ function applySourceFile(srcFile) {
Player.company_rep_mult *= incMult; Player.company_rep_mult *= incMult;
break; break;
case 12: //The testing ground case 12: //The testing ground
var inc = Math.pow(1.01, srcFile.lvl); var inc = 1 + (srcFile.level/100);
var dec = Math.pow(0.99, srcFile.lvl); var dec = 1 - (srcFile.level/100);
Player.hacking_chance_mult *= inc; Player.hacking_chance_mult *= inc;
Player.hacking_speed_mult *= inc; Player.hacking_speed_mult *= inc;

11
src/types.ts Normal file

@ -0,0 +1,11 @@
/**
* Performs an equality check between two instances of the same type.
*/
export type EqualityFunc<T> = (a: T, b: T) => boolean;
/**
* A map is an object that holds a mapping between string keys and some consistent type.
*/
export interface IMap<T> {
[key: string]: T;
}

@ -6,6 +6,9 @@ import {dialogBoxCreate} from "./DialogBox";
import {clearEventListeners} from "./HelperFunctions"; import {clearEventListeners} from "./HelperFunctions";
import {formatNumber} from "./StringHelperFunctions"; import {formatNumber} from "./StringHelperFunctions";
//Keep track of last faction
var lastFac = "";
/* InfiltrationBox.js */ /* InfiltrationBox.js */
function infiltrationBoxClose() { function infiltrationBoxClose() {
var box = document.getElementById("infiltration-box-container"); var box = document.getElementById("infiltration-box-container");
@ -60,12 +63,22 @@ function infiltrationBoxCreate(inst) {
"that faction."); "that faction.");
var selector = document.getElementById("infiltration-faction-select"); var selector = document.getElementById("infiltration-faction-select");
selector.innerHTML = ""; selector.innerHTML = "";
for (var i = 0; i < Player.factions.length; ++i) { for (let i = 0; i < Player.factions.length; ++i) {
if (Player.factions[i] === "Bladeburners") {continue;} if (Player.factions[i] === "Bladeburners") {continue;}
selector.innerHTML += "<option value='" + Player.factions[i] + selector.innerHTML += "<option value='" + Player.factions[i] +
"'>" + Player.factions[i] + "</option>"; "'>" + Player.factions[i] + "</option>";
} }
//Set initial value, if applicable
if (lastFac !== "") {
for (let i = 0; i < selector.options.length; ++i) {
if (selector.options[i].value === lastFac) {
selector.selectedIndex = i;
break;
}
}
}
var sellButton = clearEventListeners("infiltration-box-sell"); var sellButton = clearEventListeners("infiltration-box-sell");
setTimeout(function() { setTimeout(function() {
sellButton.addEventListener("click", function() { sellButton.addEventListener("click", function() {
@ -88,6 +101,7 @@ function infiltrationBoxCreate(inst) {
setTimeout(function() { setTimeout(function() {
factionButton.addEventListener("click", function() { factionButton.addEventListener("click", function() {
var facName = selector.options[selector.selectedIndex].value; var facName = selector.options[selector.selectedIndex].value;
lastFac = facName;
var faction = Factions[facName]; var faction = Factions[facName];
if (faction == null) { if (faction == null) {
dialogBoxCreate("Error finding faction. This is a bug please report to developer"); dialogBoxCreate("Error finding faction. This is a bug please report to developer");

@ -1,3 +1,4 @@
import { EqualityFunc } from "../src/types";
import { dialogBoxCreate } from "./DialogBox"; import { dialogBoxCreate } from "./DialogBox";
// Netburner String helper functions // Netburner String helper functions
@ -13,11 +14,11 @@ e.g. 10000 -> "0 hours 0 minutes and 10 seconds"
120000 -> "0 0 hours 2 minutes and 0 seconds" 120000 -> "0 0 hours 2 minutes and 0 seconds"
*/ */
function convertTimeMsToTimeElapsedString(time: number): string { function convertTimeMsToTimeElapsedString(time: number): string {
const millisecondsPerSecond = 1000; const millisecondsPerSecond: number = 1000;
const secondPerMinute = 60; const secondPerMinute: number = 60;
const minutesPerHours = 60; const minutesPerHours: number = 60;
const secondPerHours: number = secondPerMinute * minutesPerHours; const secondPerHours: number = secondPerMinute * minutesPerHours;
const hoursPerDays = 24; const hoursPerDays: number = 24;
const secondPerDay: number = secondPerHours * hoursPerDays; const secondPerDay: number = secondPerHours * hoursPerDays;
// Convert ms to seconds, since we only have second-level precision // Convert ms to seconds, since we only have second-level precision
@ -34,10 +35,10 @@ function convertTimeMsToTimeElapsedString(time: number): string {
const seconds: number = secTruncMinutes; const seconds: number = secTruncMinutes;
let res = ""; let res: string = "";
if (days) {res += `${days} days `; } if (days > 0) {res += `${days} days `; }
if (hours) {res += `${hours} hours `; } if (hours > 0) {res += `${hours} hours `; }
if (minutes) {res += `${minutes} minutes `; } if (minutes > 0) {res += `${minutes} minutes `; }
res += `${seconds} seconds `; res += `${seconds} seconds `;
return res; return res;
@ -46,14 +47,18 @@ function convertTimeMsToTimeElapsedString(time: number): string {
// Finds the longest common starting substring in a set of strings // Finds the longest common starting substring in a set of strings
function longestCommonStart(strings: string[]): string { function longestCommonStart(strings: string[]): string {
if (!containsAllStrings(strings)) {return ""; } if (!containsAllStrings(strings)) {return ""; }
if (strings.length == 0) {return ""; } if (strings.length === 0) {return ""; }
const A: string[] = strings.concat().sort(); const A: string[] = strings.concat()
.sort();
const a1: string = A[0]; const a1: string = A[0];
const a2: string = A[A.length - 1]; const a2: string = A[A.length - 1];
const L: number = a1.length; const L: number = a1.length;
let i = 0; let i: number = 0;
while (i < L && a1.charAt(i).toLowerCase() === a2.charAt(i).toLowerCase()) { i++; } const areEqualCaseInsensitive: EqualityFunc<string> = (a: string, b: string) => a.toUpperCase() === b.toUpperCase();
while (i < L && areEqualCaseInsensitive(a1, a2)) {
i++;
}
return a1.substring(0, i); return a1.substring(0, i);
} }
@ -78,16 +83,16 @@ function formatNumber(num: number, numFractionDigits: number): string {
// Count the number of times a substring occurs in a string // Count the number of times a substring occurs in a string
function numOccurrences(text: string, subString: string): number { function numOccurrences(text: string, subString: string): number {
text += ""; const input: string = `${text}`;
subString += ""; const search: string = `${subString}`;
if (subString.length <= 0) { return (text.length + 1); } if (search.length <= 0) { return (input.length + 1); }
let n = 0; let n: number = 0;
let pos = 0; let pos: number = 0;
const step: number = subString.length; const step: number = search.length;
while (true) { while (true) {
pos = text.indexOf(subString, pos); pos = input.indexOf(search, pos);
if (pos >= 0) { if (pos >= 0) {
++n; ++n;
pos += step; pos += step;
@ -113,7 +118,8 @@ function numNetscriptOperators(text: string): number {
numOccurrences(text, "==") + numOccurrences(text, "==") +
numOccurrences(text, "!="); numOccurrences(text, "!=");
if (isNaN(total)) { if (isNaN(total)) {
const message = "ERROR in counting number of operators in script. This is a bug, please report to game developer"; // tslint:disable-next-line:max-line-length
const message: string = "ERROR in counting number of operators in script. This is a bug, please report to game developer";
dialogBoxCreate(message, false); dialogBoxCreate(message, false);
return 0; return 0;
@ -124,11 +130,13 @@ function numNetscriptOperators(text: string): number {
// Checks if a string contains HTML elements // Checks if a string contains HTML elements
function isHTML(str: string): boolean { function isHTML(str: string): boolean {
const a = document.createElement("div"); const element: HTMLDivElement = document.createElement("div");
a.innerHTML = str; element.innerHTML = str;
const c = a.childNodes; const c: NodeListOf<Node & ChildNode> = element.childNodes;
for (let i = c.length; i--;) { for (let i: number = c.length; i >= 0; i--) {
if (c[i].nodeType == 1) { return true; } if (c[i].nodeType === 1) {
return true;
}
} }
return false; return false;
@ -136,10 +144,10 @@ function isHTML(str: string): boolean {
// Generates a random alphanumeric string with N characters // Generates a random alphanumeric string with N characters
function generateRandomString(n: number): string { function generateRandomString(n: number): string {
let str = ""; let str: string = "";
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; const chars: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (let i = 0; i < n; i++) { for (let i: number = 0; i < n; i++) {
str += chars.charAt(Math.floor(Math.random() * chars.length)); str += chars.charAt(Math.floor(Math.random() * chars.length));
} }