mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-20 21:25:47 +01:00
write()/read() now work for script files. You can now use angled brackets in tprint() (and create DOM elements). Added CodingContract implementation
This commit is contained in:
parent
b66c3c6fc4
commit
420fd0c5ad
203
src/CodingContracts.ts
Normal file
203
src/CodingContracts.ts
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||||
|
import { createElement } from "../utils/uiHelpers/createElement";
|
||||||
|
import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||||
|
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||||
|
import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, SolverFunc } from "./data/codingcontracttypes";
|
||||||
|
import { IMap } from "./types";
|
||||||
|
|
||||||
|
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
||||||
|
|
||||||
|
/* Represents different types of problems that a Coding Contract can have */
|
||||||
|
export class ContractType {
|
||||||
|
/**
|
||||||
|
* Function that generates a description of the problem
|
||||||
|
*/
|
||||||
|
desc: DescriptionFunc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number that generally represents the problem's difficulty. Bigger numbers = harder
|
||||||
|
*/
|
||||||
|
difficulty: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that randomly generates a valid 'data' for the problem
|
||||||
|
*/
|
||||||
|
generate: GeneratorFunc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the type of problem
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of tries the player gets on this kind of problem before it self-destructs
|
||||||
|
*/
|
||||||
|
numTries: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a function that checks if the provided answer is correct
|
||||||
|
*/
|
||||||
|
solver: SolverFunc;
|
||||||
|
|
||||||
|
constructor(name: string,
|
||||||
|
desc: DescriptionFunc,
|
||||||
|
gen: GeneratorFunc,
|
||||||
|
solver: SolverFunc,
|
||||||
|
diff: number,
|
||||||
|
numTries: number) {
|
||||||
|
this.name = name;
|
||||||
|
this.desc = desc;
|
||||||
|
this.generate = gen;
|
||||||
|
this.solver = solver;
|
||||||
|
this.difficulty = diff;
|
||||||
|
this.numTries = numTries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Contract Types */
|
||||||
|
// tslint:disable-next-line
|
||||||
|
export const ContractTypes: IMap<ContractType> = {};
|
||||||
|
|
||||||
|
for (const md of codingContractTypesMetadata) {
|
||||||
|
ContractTypes[md.name] = new ContractType(md.name, md.desc, md.gen, md.solver, md.difficulty, md.numTries);
|
||||||
|
}
|
||||||
|
console.info(`${Object.keys(ContractTypes).length} Coding Contract Types loaded`);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum representing the different types of rewards a Coding Contract can give
|
||||||
|
*/
|
||||||
|
export enum CodingContractRewardType {
|
||||||
|
FactionReputation,
|
||||||
|
FactionReputationAll,
|
||||||
|
CompanyReputation,
|
||||||
|
Money,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum representing the result when trying to solve the Contract
|
||||||
|
*/
|
||||||
|
export enum CodingContractResult {
|
||||||
|
Success,
|
||||||
|
Failure,
|
||||||
|
Cancelled,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that represents the type of reward a contract gives
|
||||||
|
*/
|
||||||
|
export interface ICodingContractReward {
|
||||||
|
/* Name of Company/Faction name for reward, if applicable */
|
||||||
|
name?: string;
|
||||||
|
type: CodingContractRewardType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Coding Contract is a file that poses a programming-related problem to the Player.
|
||||||
|
* The player receives a reward if the problem is solved correctly
|
||||||
|
*/
|
||||||
|
export class CodingContract {
|
||||||
|
/**
|
||||||
|
* Initiatizes a CodingContract from a JSON save state.
|
||||||
|
*/
|
||||||
|
static fromJSON(value: any): CodingContract {
|
||||||
|
return Generic_fromJSON(CodingContract, value.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Relevant data for the contract's problem */
|
||||||
|
data: any;
|
||||||
|
|
||||||
|
/* Contract's filename */
|
||||||
|
fn: string;
|
||||||
|
|
||||||
|
/* Describes the reward given if this Contract is solved. The reward is actually
|
||||||
|
processed outside of this file */
|
||||||
|
reward: ICodingContractReward | null;
|
||||||
|
|
||||||
|
/* Number of times the Contract has been attempted */
|
||||||
|
tries: number = 0;
|
||||||
|
|
||||||
|
/* String representing the contract's type. Must match type in ContractTypes */
|
||||||
|
type: string;
|
||||||
|
|
||||||
|
constructor(fn: string = "",
|
||||||
|
type: string = "Find Largest Prime Factor",
|
||||||
|
reward: ICodingContractReward | null = null) {
|
||||||
|
this.fn = fn;
|
||||||
|
if (!this.fn.endsWith(".cct")) {
|
||||||
|
this.fn += ".cct";
|
||||||
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line
|
||||||
|
if (ContractTypes[type] == null) {
|
||||||
|
throw new Error(`Error: invalid contract type: ${type} please contact developer`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.type = type;
|
||||||
|
this.data = ContractTypes[type].generate();
|
||||||
|
this.reward = reward;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDifficulty(): number {
|
||||||
|
return ContractTypes[this.type].difficulty;
|
||||||
|
}
|
||||||
|
|
||||||
|
getMaxNumTries(): number {
|
||||||
|
return ContractTypes[this.type].numTries;
|
||||||
|
}
|
||||||
|
|
||||||
|
isSolution(solution: string): boolean {
|
||||||
|
return ContractTypes[this.type].solver(this.data, solution);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a popup to prompt the player to solve the problem
|
||||||
|
*/
|
||||||
|
async prompt(): Promise<CodingContractResult> {
|
||||||
|
// tslint:disable-next-line
|
||||||
|
return new Promise<CodingContractResult>((resolve: Function, reject: Function) => {
|
||||||
|
const contractType: ContractType = ContractTypes[this.type];
|
||||||
|
const popupId: string = `coding-contract-prompt-popup-${this.fn}`;
|
||||||
|
const txt: HTMLElement = createElement("p", {
|
||||||
|
innerText: ["You are attempting to solve a Coding Contract. Note that",
|
||||||
|
"you only have one chance. Providing the wrong solution",
|
||||||
|
"will cause the contract to self-destruct.\n\n",
|
||||||
|
`${contractType.desc(this.data)}`].join(" "),
|
||||||
|
});
|
||||||
|
const answerInput: HTMLInputElement = createElement("input", {
|
||||||
|
placeholder: "Enter Solution here",
|
||||||
|
}) as HTMLInputElement;
|
||||||
|
const solveBtn: HTMLElement = createElement("a", {
|
||||||
|
class: "a-link-button",
|
||||||
|
clickListener: () => {
|
||||||
|
const answer: string = answerInput.value;
|
||||||
|
if (this.isSolution(answer)) {
|
||||||
|
resolve(CodingContractResult.Success);
|
||||||
|
} else {
|
||||||
|
resolve(CodingContractResult.Failure);
|
||||||
|
}
|
||||||
|
removeElementById(popupId);
|
||||||
|
},
|
||||||
|
innerText: "Solve",
|
||||||
|
});
|
||||||
|
const cancelBtn: HTMLElement = createElement("a", {
|
||||||
|
class: "a-link-button",
|
||||||
|
clickListener: () => {
|
||||||
|
resolve(CodingContractResult.Cancelled);
|
||||||
|
removeElementById(popupId);
|
||||||
|
},
|
||||||
|
innerText: "Cancel",
|
||||||
|
});
|
||||||
|
const lineBreak: HTMLElement = createElement("br");
|
||||||
|
createPopup(popupId, [txt, lineBreak, lineBreak, answerInput, solveBtn, cancelBtn]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the current file to a JSON save state.
|
||||||
|
*/
|
||||||
|
toJSON(): any {
|
||||||
|
return Generic_toJSON("CodingContract", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Reviver.constructors.CodingContract = CodingContract;
|
@ -85,6 +85,8 @@ let CONSTANTS = {
|
|||||||
ScriptGetScriptRamCost: 0.1,
|
ScriptGetScriptRamCost: 0.1,
|
||||||
ScriptGetHackTimeRamCost: 0.05,
|
ScriptGetHackTimeRamCost: 0.05,
|
||||||
ScriptGetFavorToDonate: 0.10,
|
ScriptGetFavorToDonate: 0.10,
|
||||||
|
ScriptGetContractDataRamCost: 25,
|
||||||
|
ScriptAttemptContractRamCost: 25,
|
||||||
|
|
||||||
ScriptSingularityFn1RamCost: 1,
|
ScriptSingularityFn1RamCost: 1,
|
||||||
ScriptSingularityFn2RamCost: 2,
|
ScriptSingularityFn2RamCost: 2,
|
||||||
@ -191,12 +193,13 @@ let CONSTANTS = {
|
|||||||
"-Nodes slowly regenerate health over time.",
|
"-Nodes slowly regenerate health over time.",
|
||||||
|
|
||||||
|
|
||||||
//Gang constants
|
/* Gang constant */
|
||||||
GangRespectToReputationRatio: 2, //Respect is divided by this to get rep gain
|
GangRespectToReputationRatio: 2, //Respect is divided by this to get rep gain
|
||||||
MaximumGangMembers: 20,
|
MaximumGangMembers: 20,
|
||||||
GangRecruitCostMultiplier: 2,
|
GangRecruitCostMultiplier: 2,
|
||||||
GangTerritoryUpdateTimer: 150,
|
GangTerritoryUpdateTimer: 150,
|
||||||
|
|
||||||
|
/* Time Constants */
|
||||||
MillisecondsPer20Hours: 72000000,
|
MillisecondsPer20Hours: 72000000,
|
||||||
GameCyclesPer20Hours: 72000000 / 200,
|
GameCyclesPer20Hours: 72000000 / 200,
|
||||||
|
|
||||||
@ -224,6 +227,7 @@ let CONSTANTS = {
|
|||||||
MillisecondsPerFiveMinutes: 300000,
|
MillisecondsPerFiveMinutes: 300000,
|
||||||
GameCyclesPerFiveMinutes: 300000 / 200,
|
GameCyclesPerFiveMinutes: 300000 / 200,
|
||||||
|
|
||||||
|
/* Player Work / Action related Constants */
|
||||||
FactionWorkHacking: "Faction Hacking Work",
|
FactionWorkHacking: "Faction Hacking Work",
|
||||||
FactionWorkField: "Faction Field Work",
|
FactionWorkField: "Faction Field Work",
|
||||||
FactionWorkSecurity: "Faction Security Work",
|
FactionWorkSecurity: "Faction Security Work",
|
||||||
@ -267,6 +271,11 @@ let CONSTANTS = {
|
|||||||
CrimeAssassination: "assassinate a high-profile target",
|
CrimeAssassination: "assassinate a high-profile target",
|
||||||
CrimeHeist: "pull off the ultimate heist",
|
CrimeHeist: "pull off the ultimate heist",
|
||||||
|
|
||||||
|
/* Coding Contract Constants */
|
||||||
|
CodingContractBaseFactionRepGain: 2500,
|
||||||
|
CodingContractBaseCompanyRepGain: 4000,
|
||||||
|
CodingContractBaseMoneyGain: 10e6,
|
||||||
|
|
||||||
/* Tutorial related things */
|
/* Tutorial related things */
|
||||||
TutorialNetworkingText: "Servers are a central part of the game. You start with a single personal server (your home computer) " +
|
TutorialNetworkingText: "Servers are a central part of the game. You start with a single personal server (your home computer) " +
|
||||||
"and you can purchase additional servers as you progress through the game. Connecting to other servers " +
|
"and you can purchase additional servers as you progress through the game. Connecting to other servers " +
|
||||||
@ -497,7 +506,13 @@ let CONSTANTS = {
|
|||||||
"World Stock Exchange account and TIX API Access<br>",
|
"World Stock Exchange account and TIX API Access<br>",
|
||||||
|
|
||||||
LatestUpdate:
|
LatestUpdate:
|
||||||
`v0.40.3<br>
|
`
|
||||||
|
v0.40.4<br>
|
||||||
|
* (TODO NEEDS DOCUMENTATION) The write() and read() Netscript functions now work on scripts<br>
|
||||||
|
* It is now possible to use freely use angled bracket (<, >) and create DOM elements using tprint()<br>
|
||||||
|
* Added Coding Contracts (not yet generated in game, but the data/implementation exists)<br>
|
||||||
|
|
||||||
|
v0.40.3<br>
|
||||||
-----------------------------------------------<br>
|
-----------------------------------------------<br>
|
||||||
* Bladeburner Changes:<br>
|
* Bladeburner Changes:<br>
|
||||||
*** Increased the effect that agi and dexterity have on action time<br>
|
*** Increased the effect that agi and dexterity have on action time<br>
|
||||||
|
@ -475,13 +475,6 @@ function NetscriptFunctions(workerScript) {
|
|||||||
throw makeRuntimeRejectMsg(workerScript, "tprint() call has incorrect number of arguments. Takes 1 argument");
|
throw makeRuntimeRejectMsg(workerScript, "tprint() call has incorrect number of arguments. Takes 1 argument");
|
||||||
}
|
}
|
||||||
var x = args.toString();
|
var x = args.toString();
|
||||||
if (isHTML(x)) {
|
|
||||||
Player.takeDamage(1);
|
|
||||||
dialogBoxCreate("You suddenly feel a sharp shooting pain through your body as an angry voice in your head exclaims: <br><br>" +
|
|
||||||
"DON'T USE TPRINT() TO OUTPUT HTML ELEMENTS TO YOUR TERMINAL!!!!<br><br>" +
|
|
||||||
"(You lost 1 HP)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
post(workerScript.scriptRef.filename + ": " + args.toString());
|
post(workerScript.scriptRef.filename + ": " + args.toString());
|
||||||
},
|
},
|
||||||
clearLog : function() {
|
clearLog : function() {
|
||||||
@ -1839,13 +1832,26 @@ function NetscriptFunctions(workerScript) {
|
|||||||
throw makeRuntimeRejectMsg(workerScript, "Could not find port: " + port + ". This is a bug contact the game developer");
|
throw makeRuntimeRejectMsg(workerScript, "Could not find port: " + port + ". This is a bug contact the game developer");
|
||||||
}
|
}
|
||||||
return port.write(data);
|
return port.write(data);
|
||||||
} else if (isString(port)) { //Write to text file
|
} else if (isString(port)) { //Write to script or text file
|
||||||
var fn = port;
|
var fn = port;
|
||||||
var server = getServer(workerScript.serverIp);
|
var server = workerScript.getServer();
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in write(). This is a bug please contact game dev");
|
throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in write(). This is a bug please contact game dev");
|
||||||
}
|
}
|
||||||
var txtFile = getTextFile(fn, server);
|
if (isScriptFilename(fn)) {
|
||||||
|
//Write to script
|
||||||
|
let script = workerScript.getScriptOnServer(fn);
|
||||||
|
if (script == null) {
|
||||||
|
//Create a new script
|
||||||
|
script = new Script(fn, data, server.ip);
|
||||||
|
server.scripts.push(script);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
mode === "w" ? script.code = data : script.code += data;
|
||||||
|
script.updateRamUsage();
|
||||||
|
} else {
|
||||||
|
//Write to text file
|
||||||
|
let txtFile = getTextFile(fn, server);
|
||||||
if (txtFile == null) {
|
if (txtFile == null) {
|
||||||
txtFile = createTextFile(fn, data, server);
|
txtFile = createTextFile(fn, data, server);
|
||||||
return true;
|
return true;
|
||||||
@ -1855,6 +1861,7 @@ function NetscriptFunctions(workerScript) {
|
|||||||
} else {
|
} else {
|
||||||
txtFile.append(data);
|
txtFile.append(data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for write: " + port);
|
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for write: " + port);
|
||||||
@ -1895,18 +1902,28 @@ function NetscriptFunctions(workerScript) {
|
|||||||
throw makeRuntimeRejectMsg(workerScript, "ERROR: Could not find port: " + port + ". This is a bug contact the game developer");
|
throw makeRuntimeRejectMsg(workerScript, "ERROR: Could not find port: " + port + ". This is a bug contact the game developer");
|
||||||
}
|
}
|
||||||
return port.read();
|
return port.read();
|
||||||
} else if (isString(port)) { //Read from text file
|
} else if (isString(port)) { //Read from script or text file
|
||||||
var fn = port;
|
let fn = port;
|
||||||
var server = getServer(workerScript.serverIp);
|
let server = getServer(workerScript.serverIp);
|
||||||
if (server == null) {
|
if (server == null) {
|
||||||
throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in read(). This is a bug please contact game dev");
|
throw makeRuntimeRejectMsg(workerScript, "Error getting Server for this script in read(). This is a bug please contact game dev");
|
||||||
}
|
}
|
||||||
var txtFile = getTextFile(fn, server);
|
if (isScriptFilename(fn)) {
|
||||||
|
//Read from script
|
||||||
|
let script = workerScript.getScriptOnServer(fn);
|
||||||
|
if (script == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return script.code;
|
||||||
|
} else {
|
||||||
|
//Read from text file
|
||||||
|
let txtFile = getTextFile(fn, server);
|
||||||
if (txtFile !== null) {
|
if (txtFile !== null) {
|
||||||
return txtFile.text;
|
return txtFile.text;
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for read(): " + port);
|
throw makeRuntimeRejectMsg(workerScript, "Invalid argument passed in for read(): " + port);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ WorkerScript.prototype.getServer = function() {
|
|||||||
//Returns the Script object for the underlying script
|
//Returns the Script object for the underlying script
|
||||||
WorkerScript.prototype.getScript = function() {
|
WorkerScript.prototype.getScript = function() {
|
||||||
let server = this.getServer();
|
let server = this.getServer();
|
||||||
for (var i = 0; i < server.scripts.length; ++i) {
|
for (let i = 0; i < server.scripts.length; ++i) {
|
||||||
if (server.scripts[i].filename === this.name) {
|
if (server.scripts[i].filename === this.name) {
|
||||||
return server.scripts[i];
|
return server.scripts[i];
|
||||||
}
|
}
|
||||||
@ -66,6 +66,19 @@ WorkerScript.prototype.getScript = function() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Returns the Script object for the specified script
|
||||||
|
WorkerScript.prototype.getScriptOnServer = function(fn, server) {
|
||||||
|
if (server == null) {
|
||||||
|
server = this.getServer();
|
||||||
|
}
|
||||||
|
for (let i = 0; i < server.scripts.length; ++i) {
|
||||||
|
if (server.scripts[i].filename === fn) {
|
||||||
|
return server.scripts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
WorkerScript.prototype.shouldLog = function(fn) {
|
WorkerScript.prototype.shouldLog = function(fn) {
|
||||||
return (this.disableLogs.ALL == null && this.disableLogs[fn] == null);
|
return (this.disableLogs.ALL == null && this.disableLogs[fn] == null);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import {Augmentations, applyAugmentation,
|
|||||||
AugmentationNames,
|
AugmentationNames,
|
||||||
PlayerOwnedAugmentation} from "./Augmentations";
|
PlayerOwnedAugmentation} from "./Augmentations";
|
||||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||||
|
import {CodingContractRewardType} from "./CodingContracts";
|
||||||
import {Company, Companies, getNextCompanyPosition,
|
import {Company, Companies, getNextCompanyPosition,
|
||||||
getJobRequirementText, CompanyPosition,
|
getJobRequirementText, CompanyPosition,
|
||||||
CompanyPositions} from "./Company";
|
CompanyPositions} from "./Company";
|
||||||
@ -2278,6 +2279,52 @@ PlayerObject.prototype.queueAugmentation = function(name) {
|
|||||||
this.queuedAugmentations.push(new PlayerOwnedAugmentation(name));
|
this.queuedAugmentations.push(new PlayerOwnedAugmentation(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************* Coding Contracts **************/
|
||||||
|
PlayerObject.prototype.gainCodingContractReward = function(reward, difficulty=1) {
|
||||||
|
if (reward == null || reward.type == null || reward == null) {
|
||||||
|
return `No reward for this contract`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable no-case-declarations */
|
||||||
|
switch (reward.type) {
|
||||||
|
case CodingContractRewardType.FactionReputation:
|
||||||
|
if (reward.name == null || !(Factions[reward.name] instanceof Faction)) {
|
||||||
|
// If no/invalid faction was designated, just give rewards to all factions
|
||||||
|
reward.type = CodingContractRewardType.FactionReputationAll;
|
||||||
|
return this.gainCodingContractReward(reward);
|
||||||
|
}
|
||||||
|
var repGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||||
|
Factions[reward.name].playerReputation += repGain;
|
||||||
|
return `Gained ${repGain} faction reputation for ${reward.name}`;
|
||||||
|
case CodingContractRewardType.FactionReputationAll:
|
||||||
|
const totalGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||||
|
const gainPerFaction = Math.floor(totalGain / this.factions.length);
|
||||||
|
for (const facName of this.factions) {
|
||||||
|
if (!(Factions[facName] instanceof Faction)) { continue; }
|
||||||
|
Factions[facName].playerReputation += gainPerFaction;
|
||||||
|
}
|
||||||
|
return `Gained ${gainPerFaction} reputation for each faction you are a member of`;
|
||||||
|
break;
|
||||||
|
case CodingContractRewardType.CompanyReputation:
|
||||||
|
if (reward.name == null || !(Companies[reward.name] instanceof Company)) {
|
||||||
|
//If no/invalid company was designated, just give rewards to all factions
|
||||||
|
reward.type = CodingContractRewardType.FactionReputationAll;
|
||||||
|
return this.gainCodingContractReward(reward);
|
||||||
|
}
|
||||||
|
var repGain = CONSTANTS.CodingContractBaseCompanyRepGain * difficulty;
|
||||||
|
Companies[reward.name].playerReputation += repGain;
|
||||||
|
return `Gained ${repGain} company reputation for ${reward.name}`;
|
||||||
|
break;
|
||||||
|
case CodingContractRewardType.Money:
|
||||||
|
default:
|
||||||
|
var moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty;
|
||||||
|
this.gainMoney(moneyGain);
|
||||||
|
return `Gained ${numeralWrapper.format(moneyGain, '$0.000a')}`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* eslint-enable no-case-declarations */
|
||||||
|
}
|
||||||
|
|
||||||
/* Functions for saving and loading the Player data */
|
/* Functions for saving and loading the Player data */
|
||||||
function loadPlayer(saveString) {
|
function loadPlayer(saveString) {
|
||||||
Player = JSON.parse(saveString, Reviver);
|
Player = JSON.parse(saveString, Reviver);
|
||||||
|
@ -371,12 +371,13 @@ function checkValidFilename(filename) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Script() {
|
function Script(fn = "", code = "", server = "") {
|
||||||
this.filename = "";
|
this.filename = fn;
|
||||||
this.code = "";
|
this.code = code;
|
||||||
this.ramUsage = 0;
|
this.ramUsage = 0;
|
||||||
this.server = ""; //IP of server this script is on
|
this.server = server; //IP of server this script is on
|
||||||
this.module = "";
|
this.module = "";
|
||||||
|
if (this.code !== "") {this.updateRamUsage();}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Get the script data from the Script Editor and save it to the object
|
//Get the script data from the Script Editor and save it to the object
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
import {BitNodeMultipliers} from "./BitNodeMultipliers";
|
||||||
|
import {CodingContract, ContractTypes} from "./CodingContracts";
|
||||||
import {CONSTANTS} from "./Constants";
|
import {CONSTANTS} from "./Constants";
|
||||||
import {Programs} from "./CreateProgram";
|
import {Programs} from "./CreateProgram";
|
||||||
import {Player} from "./Player";
|
import {Player} from "./Player";
|
||||||
@ -42,6 +43,7 @@ function Server(params={ip:createRandomIp(), hostname:""}) {
|
|||||||
this.programs = [];
|
this.programs = [];
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
this.textFiles = [];
|
this.textFiles = [];
|
||||||
|
this.contracts = [];
|
||||||
this.dir = 0; //new Directory(this, null, ""); TODO
|
this.dir = 0; //new Directory(this, null, ""); TODO
|
||||||
|
|
||||||
/* Hacking information (only valid for "foreign" aka non-purchased servers) */
|
/* Hacking information (only valid for "foreign" aka non-purchased servers) */
|
||||||
@ -113,6 +115,32 @@ Server.prototype.weaken = function(amt) {
|
|||||||
this.capDifficulty();
|
this.capDifficulty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Coding Contracts
|
||||||
|
Server.prototype.addContract = function(contract) {
|
||||||
|
this.contracts.push(contract);
|
||||||
|
}
|
||||||
|
|
||||||
|
Server.prototype.removeContract = function(contract) {
|
||||||
|
if (contract instanceof CodingContract) {
|
||||||
|
this.contracts = this.contracts.filter((c) => {
|
||||||
|
return c.fn !== contract.fn;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.contracts = this.contracts.filter((c) => {
|
||||||
|
return c.fn !== contract;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Server.prototype.getContract = function(contractName) {
|
||||||
|
for (const contract of this.contracts) {
|
||||||
|
if (contract.fn === contractName) {
|
||||||
|
return contract;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
//Functions for loading and saving a Server
|
//Functions for loading and saving a Server
|
||||||
Server.prototype.toJSON = function() {
|
Server.prototype.toJSON = function() {
|
||||||
return Generic_toJSON("Server", this);
|
return Generic_toJSON("Server", this);
|
||||||
|
@ -2,6 +2,8 @@ import {substituteAliases, printAliases,
|
|||||||
parseAliasDeclaration,
|
parseAliasDeclaration,
|
||||||
removeAlias, GlobalAliases,
|
removeAlias, GlobalAliases,
|
||||||
Aliases} from "./Alias";
|
Aliases} from "./Alias";
|
||||||
|
import {CodingContract, CodingContractResult,
|
||||||
|
CodingContractRewardType} from "./CodingContracts";
|
||||||
import {CONSTANTS} from "./Constants";
|
import {CONSTANTS} from "./Constants";
|
||||||
import {Programs} from "./CreateProgram";
|
import {Programs} from "./CreateProgram";
|
||||||
import {executeDarkwebTerminalCommand,
|
import {executeDarkwebTerminalCommand,
|
||||||
@ -62,7 +64,7 @@ $(document).keydown(function(event) {
|
|||||||
//Terminal
|
//Terminal
|
||||||
if (routing.isOn(Page.Terminal)) {
|
if (routing.isOn(Page.Terminal)) {
|
||||||
var terminalInput = document.getElementById("terminal-input-text-box");
|
var terminalInput = document.getElementById("terminal-input-text-box");
|
||||||
if (terminalInput != null && !event.ctrlKey && !event.shiftKey) {terminalInput.focus();}
|
if (terminalInput != null && !event.ctrlKey && !event.shiftKey && !Terminal.contractOpen) {terminalInput.focus();}
|
||||||
|
|
||||||
if (event.keyCode === KEY.ENTER) {
|
if (event.keyCode === KEY.ENTER) {
|
||||||
event.preventDefault(); //Prevent newline from being entered in Script Editor
|
event.preventDefault(); //Prevent newline from being entered in Script Editor
|
||||||
@ -251,7 +253,7 @@ $(document).keydown(function(e) {
|
|||||||
terminalCtrlPressed = true;
|
terminalCtrlPressed = true;
|
||||||
} else if (e.shiftKey) {
|
} else if (e.shiftKey) {
|
||||||
shiftKeyPressed = true;
|
shiftKeyPressed = true;
|
||||||
} else if (terminalCtrlPressed || shiftKeyPressed) {
|
} else if (terminalCtrlPressed || shiftKeyPressed || Terminal.contractOpen) {
|
||||||
//Don't focus
|
//Don't focus
|
||||||
} else {
|
} else {
|
||||||
var inputTextBox = document.getElementById("terminal-input-text-box");
|
var inputTextBox = document.getElementById("terminal-input-text-box");
|
||||||
@ -523,6 +525,8 @@ let Terminal = {
|
|||||||
commandHistory: [],
|
commandHistory: [],
|
||||||
commandHistoryIndex: 0,
|
commandHistoryIndex: 0,
|
||||||
|
|
||||||
|
contractOpen: false, //True if a Coding Contract prompt is opened
|
||||||
|
|
||||||
resetTerminalInput: function() {
|
resetTerminalInput: function() {
|
||||||
if (FconfSettings.WRAP_INPUT) {
|
if (FconfSettings.WRAP_INPUT) {
|
||||||
document.getElementById("terminal-input-td").innerHTML =
|
document.getElementById("terminal-input-td").innerHTML =
|
||||||
@ -1354,9 +1358,11 @@ let Terminal = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Check if its a script or just a program/executable
|
//Check if its a script or just a program/executable
|
||||||
//if (isScriptFilename(executableName)) {
|
//Dont use isScriptFilename here because `executableName` includes the args too
|
||||||
if (executableName.includes(".script") || executableName.includes(".js") || executableName.includes(".ns")) {
|
if (executableName.includes(".script") || executableName.includes(".js") || executableName.includes(".ns")) {
|
||||||
Terminal.runScript(executableName);
|
Terminal.runScript(executableName);
|
||||||
|
} else if (executableName.endsWith(".cct")) {
|
||||||
|
Terminal.runContract(executableName);
|
||||||
} else {
|
} else {
|
||||||
Terminal.runProgram(executableName);
|
Terminal.runProgram(executableName);
|
||||||
}
|
}
|
||||||
@ -1744,6 +1750,15 @@ let Terminal = {
|
|||||||
allFiles.push(s.textFiles[i].fn);
|
allFiles.push(s.textFiles[i].fn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (var i = 0; i < s.contracts.length; ++i) {
|
||||||
|
if (filter) {
|
||||||
|
if (s.contracts[i].fn.includes(filter)) {
|
||||||
|
allFiles.push(s.contracts[i].fn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
allFiles.push(s.contracts[i].fn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Sort the files alphabetically then print each
|
//Sort the files alphabetically then print each
|
||||||
allFiles.sort();
|
allFiles.sort();
|
||||||
@ -1969,9 +1984,9 @@ let Terminal = {
|
|||||||
post("Server base security level: " + targetServer.baseDifficulty);
|
post("Server base security level: " + targetServer.baseDifficulty);
|
||||||
post("Server current security level: " + targetServer.hackDifficulty);
|
post("Server current security level: " + targetServer.hackDifficulty);
|
||||||
post("Server growth rate: " + targetServer.serverGrowth);
|
post("Server growth rate: " + targetServer.serverGrowth);
|
||||||
post("Netscript hack() execution time: " + numeralWrapper.format(scriptCalculateHackingTime(targetServer), '0.0') + "s");
|
post("Netscript hack() execution time: " + numeralWrapper.format(calculateHackingTime(targetServer), '0.0') + "s");
|
||||||
post("Netscript grow() execution time: " + numeralWrapper.format(scriptCalculateGrowTime(targetServer), '0.0') + "s");
|
post("Netscript grow() execution time: " + numeralWrapper.format(calculateGrowTime(targetServer), '0.0') + "s");
|
||||||
post("Netscript weaken() execution time: " + numeralWrapper.format(scriptCalculateWeakenTime(targetServer), '0.0') + "s");
|
post("Netscript weaken() execution time: " + numeralWrapper.format(calculateWeakenTime(targetServer), '0.0') + "s");
|
||||||
};
|
};
|
||||||
programHandlers[Programs.AutoLink.name] = () => {
|
programHandlers[Programs.AutoLink.name] = () => {
|
||||||
post("This executable cannot be run.");
|
post("This executable cannot be run.");
|
||||||
@ -2132,7 +2147,42 @@ let Terminal = {
|
|||||||
|
|
||||||
|
|
||||||
post("ERROR: No such script");
|
post("ERROR: No such script");
|
||||||
|
},
|
||||||
|
|
||||||
|
runContract: async function(contractName) {
|
||||||
|
// There's already an opened contract
|
||||||
|
if (Terminal.contractOpen) {
|
||||||
|
return post("ERROR: There's already a Coding Contract in Progress");
|
||||||
}
|
}
|
||||||
|
Terminal.contractOpen = true;
|
||||||
|
|
||||||
|
const serv = Player.getCurrentServer();
|
||||||
|
const contract = serv.getContract(contractName);
|
||||||
|
if (contract == null) {
|
||||||
|
return post("ERROR: No such contract");
|
||||||
|
}
|
||||||
|
const res = await contract.prompt();
|
||||||
|
|
||||||
|
switch (res) {
|
||||||
|
case CodingContractResult.Success:
|
||||||
|
var reward = Player.gainCodingContractReward(contract.reward, contract.getDifficulty());
|
||||||
|
post(`Contract SUCCESS - ${reward}`);
|
||||||
|
serv.removeContract(contract);
|
||||||
|
break;
|
||||||
|
case CodingContractResult.Failure:
|
||||||
|
post("Contract <p style='color:red;display:inline'>FAILED</p> - Contract is now self-destructing");
|
||||||
|
++contract.tries;
|
||||||
|
if (contract.tries >= contract.getMaxNumTries()) {
|
||||||
|
serv.removeContract(contract);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CodingContractResult.Cancelled:
|
||||||
|
default:
|
||||||
|
post("Contract cancelled");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Terminal.contractOpen = false;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export {postNetburnerText, Terminal};
|
export {postNetburnerText, Terminal};
|
||||||
|
463
src/data/codingcontracttypes.ts
Normal file
463
src/data/codingcontracttypes.ts
Normal file
@ -0,0 +1,463 @@
|
|||||||
|
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
||||||
|
|
||||||
|
/* tslint:disable:completed-docs no-magic-numbers arrow-return-shorthand */
|
||||||
|
|
||||||
|
/* Function that generates a valid 'data' for a contract type */
|
||||||
|
export type GeneratorFunc = () => any;
|
||||||
|
|
||||||
|
/* Function that checks if the provided solution is the correct one */
|
||||||
|
export type SolverFunc = (data: any, answer: string) => boolean;
|
||||||
|
|
||||||
|
/* Function that returns a string with the problem's description.
|
||||||
|
Requires the 'data' of a Contract as input */
|
||||||
|
export type DescriptionFunc = (data: any) => string;
|
||||||
|
|
||||||
|
export interface ICodingContractTypeMetadata {
|
||||||
|
desc: DescriptionFunc;
|
||||||
|
difficulty: number;
|
||||||
|
gen: GeneratorFunc;
|
||||||
|
name: string;
|
||||||
|
numTries: number;
|
||||||
|
solver: SolverFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
||||||
|
{
|
||||||
|
desc: (n: number) => {
|
||||||
|
return ["A prime factor is a factor that is a prime number.",
|
||||||
|
`What is the largest prime factor of ${n}?`].join(" ");
|
||||||
|
},
|
||||||
|
difficulty: 1,
|
||||||
|
gen: () => {
|
||||||
|
return getRandomInt(500, 9e9);
|
||||||
|
},
|
||||||
|
name: "Find Largest Prime Factor",
|
||||||
|
numTries: 10,
|
||||||
|
solver: (data: number, ans: string) => {
|
||||||
|
let fac: number = 2;
|
||||||
|
let n: number = data;
|
||||||
|
while (n > fac) {
|
||||||
|
if (n % fac === 0) {
|
||||||
|
n = Math.round(n / fac);
|
||||||
|
fac = 2;
|
||||||
|
} else {
|
||||||
|
++fac;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fac === parseInt(ans, 10);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: (n: number[]) => {
|
||||||
|
return ["Given the following integer array, find the contiguous subarray",
|
||||||
|
"(containing at least one number) which has the largest sum and return that sum.",
|
||||||
|
"'Sum' refers to the sum of all the numbers in the subarray.",
|
||||||
|
`${n.toString()}`].join(" ");
|
||||||
|
},
|
||||||
|
difficulty: 1,
|
||||||
|
gen: () => {
|
||||||
|
const len: number = getRandomInt(5, 40);
|
||||||
|
const arr: number[] = [];
|
||||||
|
arr.length = len;
|
||||||
|
for (let i: number = 0; i < len; ++i) {
|
||||||
|
arr[i] = getRandomInt(-10, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
},
|
||||||
|
name: "Subarray with Maximum Sum",
|
||||||
|
numTries: 10,
|
||||||
|
solver: (data: number[], ans: string) => {
|
||||||
|
const nums: number[] = data.slice();
|
||||||
|
for (let i: number = 1; i < nums.length; i++) {
|
||||||
|
nums[i] = Math.max(nums[i], nums[i] + nums[i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseInt(ans, 10) === Math.max(...nums);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: (n: number) => {
|
||||||
|
return ["It is possible write four as a sum in exactly four different ways:\n\n",
|
||||||
|
" 3 + 1\n",
|
||||||
|
" 2 + 2\n",
|
||||||
|
" 2 + 1 + 1\n",
|
||||||
|
" 1 + 1 + 1 + 1\n\n",
|
||||||
|
`How many different ways can ${n} be written as a sum of at least`,
|
||||||
|
"two positive integers?"].join(" ");
|
||||||
|
},
|
||||||
|
difficulty: 1.5,
|
||||||
|
gen: () => {
|
||||||
|
return getRandomInt(8, 100);
|
||||||
|
},
|
||||||
|
name: "Total Ways to Sum",
|
||||||
|
numTries: 10,
|
||||||
|
solver: (data: number, ans: string) => {
|
||||||
|
const ways: number[] = [1];
|
||||||
|
ways.length = data + 1;
|
||||||
|
ways.fill(0, 1);
|
||||||
|
for (let i: number = 1; i < data; ++i) {
|
||||||
|
for (let j: number = i; j <= data; ++j) {
|
||||||
|
ways[j] += ways[j - i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ways[data] === parseInt(ans, 10);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: (n: number[][]) => {
|
||||||
|
let d: string = ["Given the following array of array of numbers representing a 2D matrix,",
|
||||||
|
"return the elements of the matrix as an array in spiral order:\n\n"].join(" ");
|
||||||
|
for (const line of n) {
|
||||||
|
d += `${line.toString()},\n`;
|
||||||
|
}
|
||||||
|
d += ["\nHere is an example of what spiral order should be:",
|
||||||
|
"\nExample:",
|
||||||
|
" [\n",
|
||||||
|
" [1, 2, 3],\n",
|
||||||
|
" [4, 5, 6],\n",
|
||||||
|
" [7, 8, 9]\n",
|
||||||
|
" ] should result in [1, 2, 3, 6, 9, 8 ,7, 4, 5]\n\n",
|
||||||
|
"Note that the matrix will not always be square:\n",
|
||||||
|
" [\n",
|
||||||
|
" [1, 2, 3, 4]\n",
|
||||||
|
" [5, 6, 7, 8]\n",
|
||||||
|
" [9, 10, 11, 12]\n",
|
||||||
|
" ] should result in [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7"].join(" ");
|
||||||
|
|
||||||
|
return d;
|
||||||
|
},
|
||||||
|
difficulty: 2,
|
||||||
|
gen: () => {
|
||||||
|
const m: number = getRandomInt(1, 10);
|
||||||
|
const n: number = getRandomInt(1, 10);
|
||||||
|
const matrix: number[][] = [];
|
||||||
|
matrix.length = m;
|
||||||
|
for (let i: number = 0; i < m; ++i) {
|
||||||
|
matrix[i].length = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i: number = 0; i < m; ++i) {
|
||||||
|
for (let j: number = 0; j < n; ++j) {
|
||||||
|
matrix[i][j] = getRandomInt(1, 50);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matrix;
|
||||||
|
},
|
||||||
|
name: "Spiralize Matrix",
|
||||||
|
numTries: 10,
|
||||||
|
solver: (data: number[][], ans: string) => {
|
||||||
|
const spiral: number[] = [];
|
||||||
|
const m: number = data.length;
|
||||||
|
const n: number = data[0].length;
|
||||||
|
let u: number = 0;
|
||||||
|
let d: number = m - 1;
|
||||||
|
let l: number = 0;
|
||||||
|
let r: number = n - 1;
|
||||||
|
let k: number = 0;
|
||||||
|
while (true) {
|
||||||
|
// Up
|
||||||
|
for (let col: number = l; col <= r; col++) {
|
||||||
|
spiral[k] = data[u][col];
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
if (++u > d) { break; }
|
||||||
|
|
||||||
|
// Right
|
||||||
|
for (let row: number = u; row <= d; row++) {
|
||||||
|
spiral[k] = data[row][r];
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
if (--r < l) { break; }
|
||||||
|
|
||||||
|
// Down
|
||||||
|
for (let col: number = r; col >= l; col--) {
|
||||||
|
spiral[k] = data[d][col];
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
if (--d < u) { break; }
|
||||||
|
|
||||||
|
// Left
|
||||||
|
for (let row: number = d; row >= u; row--) {
|
||||||
|
spiral[k] = data[row][l];
|
||||||
|
++k;
|
||||||
|
}
|
||||||
|
if (++l > r) { break; }
|
||||||
|
}
|
||||||
|
const playerAns: any[] = ans.split(",");
|
||||||
|
for (let i: number = 0; i < playerAns.length; ++i) {
|
||||||
|
playerAns[i] = parseInt(playerAns[i], 10);
|
||||||
|
}
|
||||||
|
if (spiral.length !== playerAns.length) { return false; }
|
||||||
|
for (let i: number = 0; i < spiral.length; ++i) {
|
||||||
|
if (spiral[i] !== playerAns[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: (arr: number[]) => {
|
||||||
|
return ["You are given the following array of integers:\n\n",
|
||||||
|
`${arr}\n\n`,
|
||||||
|
"Each element in the array represents your maximum jump length",
|
||||||
|
"at that position. Assuming you are initially positioned",
|
||||||
|
"at the start of the array, determine whether you are",
|
||||||
|
"able to reach the last index exactly.\n\n",
|
||||||
|
"Your answer should be submitted as 1 or 0, representing true and false respectively"].join(" ");
|
||||||
|
},
|
||||||
|
difficulty: 2.5,
|
||||||
|
gen: () => {
|
||||||
|
const len: number = getRandomInt(1, 25);
|
||||||
|
const arr: number[] = [];
|
||||||
|
arr.length = len;
|
||||||
|
for (let i: number = 0; i < arr.length; ++i) {
|
||||||
|
arr[i] = getRandomInt(0, 24);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: "Array Jumping Game",
|
||||||
|
numTries: 1,
|
||||||
|
solver: (data: number[], ans: string) => {
|
||||||
|
const n: number = data.length;
|
||||||
|
let i: number = 0;
|
||||||
|
for (let reach: number = 0; i < n && i <= reach; ++i) {
|
||||||
|
reach = Math.max(i + data[i], reach);
|
||||||
|
}
|
||||||
|
const solution: boolean = (i === n);
|
||||||
|
|
||||||
|
if (ans === "1" && solution) { return true; }
|
||||||
|
if (ans === "0" && !solution) { return true; }
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: (arr: number[][]) => {
|
||||||
|
return ["Given the following array of array of numbers representing a list of",
|
||||||
|
"intervals, merge all overlapping intervals.\n\n",
|
||||||
|
`${arr}\n\n`,
|
||||||
|
"Example:\n\n",
|
||||||
|
"[[1, 3], [8, 10], [2, 6], [10, 16]]\n\n",
|
||||||
|
"would merge into [[1, 6], [8, 16]].\n\n",
|
||||||
|
"The intervals must be returned in ASCENDING order.",
|
||||||
|
"You can assume that in an interval, the first number will always be",
|
||||||
|
"smaller than the second."].join(" ");
|
||||||
|
},
|
||||||
|
difficulty: 3,
|
||||||
|
gen: () => {
|
||||||
|
const intervals: number[][] = [];
|
||||||
|
const numIntervals: number = getRandomInt(1, 15);
|
||||||
|
for (let i: number = 0; i < numIntervals; ++i) {
|
||||||
|
const start: number = getRandomInt(1, 25);
|
||||||
|
const end: number = start + getRandomInt(1, 10);
|
||||||
|
intervals.push([start, end]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return intervals;
|
||||||
|
},
|
||||||
|
name: "Merge Overlapping Intervals",
|
||||||
|
numTries: 15,
|
||||||
|
solver: (data: number[][], ans: string) => {
|
||||||
|
const intervals: number[][] = data.slice();
|
||||||
|
intervals.sort((a: number[], b: number[]) => {
|
||||||
|
return a[0] - b[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
const result: number[][] = [];
|
||||||
|
let start: number = intervals[0][0];
|
||||||
|
let end: number = intervals[0][1];
|
||||||
|
for (const interval of intervals) {
|
||||||
|
if (interval[0] <= end) {
|
||||||
|
end = Math.max(end, interval[1]);
|
||||||
|
} else {
|
||||||
|
result.push([start, end]);
|
||||||
|
start = interval[0];
|
||||||
|
end = interval[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push([start, end]);
|
||||||
|
|
||||||
|
const sanitizedResult: string = result
|
||||||
|
.toString()
|
||||||
|
.replace(/\s/g, "");
|
||||||
|
const sanitizedAns: string = ans.replace(/\s/g, "");
|
||||||
|
|
||||||
|
return sanitizedResult === sanitizedAns;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: (data: string) => {
|
||||||
|
return ["Given the following string containing only digits, determine",
|
||||||
|
"an array with all possible valid IP address combinations",
|
||||||
|
"that can be created from the string:\n\n",
|
||||||
|
`${data}\n\n`,
|
||||||
|
"Example:\n\n",
|
||||||
|
"'25525511135' -> ['255.255.11.135', '255.255.111.35']"].join(" ");
|
||||||
|
},
|
||||||
|
difficulty: 3,
|
||||||
|
gen: () => {
|
||||||
|
let str: string = "";
|
||||||
|
for (let i: number = 0; i < 4; ++i) {
|
||||||
|
const num: number = getRandomInt(0, 255);
|
||||||
|
const convNum: string = num.toString();
|
||||||
|
str += convNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
},
|
||||||
|
name: "Generate IP Addresses",
|
||||||
|
numTries: 10,
|
||||||
|
solver: (data: string, ans: string) => {
|
||||||
|
const ret: string[] = [];
|
||||||
|
for (let a: number = 1; a <= 3; ++a) {
|
||||||
|
for (let b: number = 1; b <= 3; ++b) {
|
||||||
|
for (let c: number = 1; c <= 3; ++c) {
|
||||||
|
for (let d: number = 1; d <= 3; ++d) {
|
||||||
|
if (a + b + c + d === data.length) {
|
||||||
|
const A: number = parseInt(data.substring(0, a), 10);
|
||||||
|
const B: number = parseInt(data.substring(a, a + b), 10);
|
||||||
|
const C: number = parseInt(data.substring(a + b, a + b + c), 10);
|
||||||
|
const D: number = parseInt(data.substring(a + b + c, a + b + c + d), 10);
|
||||||
|
if (A <= 255 && B <= 255 && C <= 255 && D <= 255) {
|
||||||
|
const ip: string = [A.toString(), ".",
|
||||||
|
B.toString(), ".",
|
||||||
|
C.toString(), ".",
|
||||||
|
D.toString()].join("");
|
||||||
|
if (ip.length === data.length + 3) {
|
||||||
|
ret.push(ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let sanitizedAns: string = ans.replace(/\s/g, "");
|
||||||
|
if (sanitizedAns.length === 0 || sanitizedAns[0] !== "[" || sanitizedAns[sanitizedAns.length - 1] !== "]") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sanitizedAns = sanitizedAns.slice(1, -1); // Remove []
|
||||||
|
const ansArr: string[] = sanitizedAns.split(",");
|
||||||
|
if (ansArr.length !== ret.length) { return false; }
|
||||||
|
for (const ipInAns of ansArr) {
|
||||||
|
if (!ret.includes(ipInAns)) { return false; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: (data: number[]) => {
|
||||||
|
return ["You are given the following array of stock prices where the i-th element",
|
||||||
|
"represents the stock price on day i:\n\n",
|
||||||
|
`${data}\n\n`,
|
||||||
|
"Determine the maximum possible profit you can earn using at most",
|
||||||
|
"one transaction (i.e. you can only buy and sell the stock once). If no profit can be made",
|
||||||
|
"then the answer should be 0. Note",
|
||||||
|
"that you have to buy the stock before you can sell it"].join(" ");
|
||||||
|
},
|
||||||
|
difficulty: 1,
|
||||||
|
gen: () => {
|
||||||
|
const len: number = getRandomInt(1, 50);
|
||||||
|
const arr: number[] = [];
|
||||||
|
arr.length = len;
|
||||||
|
for (let i: number = 0; i < len; ++i) {
|
||||||
|
arr[i] = getRandomInt(1, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
},
|
||||||
|
name: "Algorithmic Stock Trader I",
|
||||||
|
numTries: 5,
|
||||||
|
solver: (data: number[], ans: string) => {
|
||||||
|
let maxCur: number = 0;
|
||||||
|
let maxSoFar: number = 0;
|
||||||
|
for (let i: number = 1; i < data.length; ++i) {
|
||||||
|
maxCur = Math.max(0, maxCur += data[i] - data[i - 1]);
|
||||||
|
maxSoFar = Math.max(maxCur, maxSoFar);
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxSoFar.toString() === ans;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: (data: number[]) => {
|
||||||
|
return ["You are given the following array of stock prices where the i-th element",
|
||||||
|
"represents the stock price on day i:\n\n",
|
||||||
|
`${data}\n\n`,
|
||||||
|
"Determine the maximum possible profit you can earn using as many",
|
||||||
|
"transactions as you'd like. A transaction is defined as buying",
|
||||||
|
"and then selling one share of the stock. Note that you cannot",
|
||||||
|
"engage in multiple transactions at once. In other words, you",
|
||||||
|
"must sell the stock before you buy it again.\n\n",
|
||||||
|
"If no profit can be made, then the answer should be 0"].join(" ");
|
||||||
|
},
|
||||||
|
difficulty: 2,
|
||||||
|
gen: () => {
|
||||||
|
const len: number = getRandomInt(1, 50);
|
||||||
|
const arr: number[] = [];
|
||||||
|
arr.length = len;
|
||||||
|
for (let i: number = 0; i < len; ++i) {
|
||||||
|
arr[i] = getRandomInt(1, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
},
|
||||||
|
name: "Algorithmic Stock Trader II",
|
||||||
|
numTries: 10,
|
||||||
|
solver: (data: number[], ans: string) => {
|
||||||
|
let profit: number = 0;
|
||||||
|
for (let p: number = 1; p < data.length; ++p) {
|
||||||
|
profit += Math.max(data[p] - data[p - 1], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return profit.toString() === ans;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: (data: number[]) => {
|
||||||
|
return ["You are given the following array of stock prices where the i-th element",
|
||||||
|
"represents the stock price on day i:\n\n",
|
||||||
|
`${data}\n\n`,
|
||||||
|
"Determine the maximum possible profit you can earn using at most ",
|
||||||
|
"two transactions. A transaction is defined as buying",
|
||||||
|
"and then selling one share of the stock. Note that you cannot",
|
||||||
|
"engage in multiple transactions at once. In other words, you",
|
||||||
|
"must sell the stock before you buy it again.\n\n",
|
||||||
|
"If no profit can be made, then the answer should be 0"].join(" ");
|
||||||
|
},
|
||||||
|
difficulty: 5,
|
||||||
|
gen: () => {
|
||||||
|
const len: number = getRandomInt(1, 50);
|
||||||
|
const arr: number[] = [];
|
||||||
|
arr.length = len;
|
||||||
|
for (let i: number = 0; i < len; ++i) {
|
||||||
|
arr[i] = getRandomInt(1, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
},
|
||||||
|
name: "Algorithmic Stock Trader III",
|
||||||
|
numTries: 10,
|
||||||
|
solver: (data: number[], ans: string) => {
|
||||||
|
let hold1: number = Number.MIN_SAFE_INTEGER;
|
||||||
|
let hold2: number = Number.MIN_SAFE_INTEGER;
|
||||||
|
let release1: number = 0;
|
||||||
|
let release2: number = 0;
|
||||||
|
for (const price of data) {
|
||||||
|
release2 = Math.max(release2, hold2 + price);
|
||||||
|
hold2 = Math.max(hold2, release1 - price);
|
||||||
|
release1 = Math.max(release1, hold1 + price);
|
||||||
|
hold1 = Math.max(hold1, price * -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return release2.toString() === ans;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
@ -150,7 +150,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["beyond-man.lit"],
|
literature: ["beyond-man.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 9,
|
max: 9,
|
||||||
min: 5
|
min: 5,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 40e9,
|
max: 40e9,
|
||||||
@ -226,7 +226,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
],
|
],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 9,
|
max: 9,
|
||||||
min: 7
|
min: 7,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 22e9,
|
max: 22e9,
|
||||||
@ -297,7 +297,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["simulated-reality.lit"],
|
literature: ["simulated-reality.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 11,
|
max: 11,
|
||||||
min: 7
|
min: 7,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 1800e6,
|
max: 1800e6,
|
||||||
@ -404,7 +404,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["beyond-man.lit"],
|
literature: ["beyond-man.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 8,
|
max: 8,
|
||||||
min: 5
|
min: 5,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 750e6,
|
max: 750e6,
|
||||||
@ -431,7 +431,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["A-Green-Tomorrow.lit"],
|
literature: ["A-Green-Tomorrow.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 800e6,
|
max: 800e6,
|
||||||
@ -479,7 +479,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
hostname: "univ-energy",
|
hostname: "univ-energy",
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 1200e6,
|
max: 1200e6,
|
||||||
@ -506,7 +506,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["coded-intelligence.lit"],
|
literature: ["coded-intelligence.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 900000000,
|
max: 900000000,
|
||||||
@ -533,7 +533,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["synthetic-muscles.lit"],
|
literature: ["synthetic-muscles.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 6,
|
max: 6,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 700000000,
|
max: 700000000,
|
||||||
@ -631,7 +631,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["history-of-synthoids.lit"],
|
literature: ["history-of-synthoids.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 6,
|
max: 6,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 1000000000,
|
max: 1000000000,
|
||||||
@ -706,7 +706,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
],
|
],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 900000000,
|
max: 900000000,
|
||||||
@ -755,7 +755,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["A-Green-Tomorrow.lit"],
|
literature: ["A-Green-Tomorrow.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 6,
|
max: 6,
|
||||||
min: 3
|
min: 3,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 1750000000,
|
max: 1750000000,
|
||||||
@ -825,7 +825,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
hostname: "unitalife",
|
hostname: "unitalife",
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 6,
|
max: 6,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 1100000000,
|
max: 1100000000,
|
||||||
@ -851,7 +851,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
hostname: "lexo-corp",
|
hostname: "lexo-corp",
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 800000000,
|
max: 800000000,
|
||||||
@ -877,7 +877,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
hostname: "rho-construction",
|
hostname: "rho-construction",
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 6,
|
max: 6,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 700000000,
|
max: 700000000,
|
||||||
@ -904,7 +904,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["sector-12-crime.lit"],
|
literature: ["sector-12-crime.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 750000000,
|
max: 750000000,
|
||||||
@ -930,7 +930,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
hostname: "aevum-police",
|
hostname: "aevum-police",
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 6,
|
max: 6,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 400000000,
|
max: 400000000,
|
||||||
@ -961,7 +961,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
],
|
],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 250000000,
|
max: 250000000,
|
||||||
@ -987,7 +987,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
hostname: "zb-institute",
|
hostname: "zb-institute",
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 1100000000,
|
max: 1100000000,
|
||||||
@ -1018,7 +1018,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
],
|
],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 6,
|
max: 6,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 350000000,
|
max: 350000000,
|
||||||
@ -1067,7 +1067,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["tensions-in-tech-race.lit"],
|
literature: ["tensions-in-tech-race.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 550000000,
|
max: 550000000,
|
||||||
@ -1093,7 +1093,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
hostname: "the-hub",
|
hostname: "the-hub",
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 6,
|
max: 6,
|
||||||
min: 3
|
min: 3,
|
||||||
},
|
},
|
||||||
moneyAvailable: {
|
moneyAvailable: {
|
||||||
max: 200000000,
|
max: 200000000,
|
||||||
@ -1143,7 +1143,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["simulated-reality.lit"],
|
literature: ["simulated-reality.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: 275000000,
|
moneyAvailable: 275000000,
|
||||||
networkLayer: 4,
|
networkLayer: 4,
|
||||||
@ -1370,7 +1370,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
hostname: "millenium-fitness",
|
hostname: "millenium-fitness",
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 8,
|
max: 8,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: 250000000,
|
moneyAvailable: 250000000,
|
||||||
networkLayer: 6,
|
networkLayer: 6,
|
||||||
@ -1393,7 +1393,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
hostname: "powerhouse-fitness",
|
hostname: "powerhouse-fitness",
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 6,
|
max: 6,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: 900000000,
|
moneyAvailable: 900000000,
|
||||||
networkLayer: 14,
|
networkLayer: 14,
|
||||||
@ -1436,7 +1436,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
],
|
],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 9,
|
max: 9,
|
||||||
min: 5
|
min: 5,
|
||||||
},
|
},
|
||||||
moneyAvailable: 0,
|
moneyAvailable: 0,
|
||||||
networkLayer: 11,
|
networkLayer: 11,
|
||||||
@ -1455,7 +1455,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["democracy-is-dead.lit"],
|
literature: ["democracy-is-dead.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 8,
|
max: 8,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: 0,
|
moneyAvailable: 0,
|
||||||
networkLayer: 5,
|
networkLayer: 5,
|
||||||
@ -1474,7 +1474,7 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
literature: ["democracy-is-dead.lit"],
|
literature: ["democracy-is-dead.lit"],
|
||||||
maxRamExponent: {
|
maxRamExponent: {
|
||||||
max: 7,
|
max: 7,
|
||||||
min: 4
|
min: 4,
|
||||||
},
|
},
|
||||||
moneyAvailable: 0,
|
moneyAvailable: 0,
|
||||||
networkLayer: 4,
|
networkLayer: 4,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
|
"lib" : ["es2016", "dom"],
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
|
@ -17,7 +17,7 @@ function infiltrationBoxClose() {
|
|||||||
|
|
||||||
function infiltrationBoxOpen() {
|
function infiltrationBoxOpen() {
|
||||||
var box = document.getElementById("infiltration-box-container");
|
var box = document.getElementById("infiltration-box-container");
|
||||||
box.style.display = "block";
|
box.style.display = "flex";
|
||||||
}
|
}
|
||||||
|
|
||||||
function infiltrationSetText(txt) {
|
function infiltrationSetText(txt) {
|
||||||
|
Loading…
Reference in New Issue
Block a user