fixed v3.0.0 api breaks
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
parent
d5e9028750
commit
f8c8a07f44
3679
NetscriptDefinitions.d.ts
vendored
3679
NetscriptDefinitions.d.ts
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -200,6 +200,7 @@ export const defaultMultipliers = (): Multipliers => {
|
|||
work_money: 1,
|
||||
crime_success: 1,
|
||||
crime_money: 1,
|
||||
dnet_money: 1,
|
||||
bladeburner_max_stamina: 1,
|
||||
bladeburner_stamina_gain: 1,
|
||||
bladeburner_analysis: 1,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { clampNumber } from "@/utils/utils";
|
||||
import { utils } from "@/utils/utils";
|
||||
import { getRecordEntries } from "./constants";
|
||||
|
||||
export type PartialRecord<K extends string, V> = Partial<Record<K, V>>;
|
||||
|
|
@ -176,7 +176,7 @@ export class BitNodeMultipliers {
|
|||
WorldDaemonDifficulty = 1;
|
||||
|
||||
constructor(a: PartialRecord<keyof BitNodeMultipliers, number> = {}) {
|
||||
for (const [key, value] of getRecordEntries(a)) this[key] = clampNumber(value);
|
||||
for (const [key, value] of getRecordEntries(a)) this[key] = utils.clampNumber(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { clampNumber, isValidNumber } from "@/utils/utils";
|
||||
import { Player as IPerson, Server as IServer } from "@ns";
|
||||
import { ServerConstants } from "./constants";
|
||||
import { currentNodeMults } from "./exports";
|
||||
import { Player } from "./player";
|
||||
import { utils } from "@/utils/utils";
|
||||
|
||||
export const hacking = {
|
||||
growAmount: calculateGrowMoney,
|
||||
|
|
@ -21,11 +21,7 @@ export const hacking = {
|
|||
};
|
||||
|
||||
function calculateIntelligenceBonus(intelligence: number, weight = 1): number {
|
||||
const effectiveIntelligence =
|
||||
Player.bitNodeOptions.intelligenceOverride !== undefined
|
||||
? Math.min(Player.bitNodeOptions.intelligenceOverride, intelligence)
|
||||
: intelligence;
|
||||
return 1 + (weight * Math.pow(effectiveIntelligence, 0.8)) / 600;
|
||||
return 1 + (weight * Math.pow(intelligence, 0.8)) / 600;
|
||||
}
|
||||
|
||||
/** Returns the chance the person has to successfully hack a server */
|
||||
|
|
@ -36,14 +32,14 @@ function calculateHackingChance(server: IServer, person: IPerson): number {
|
|||
if (!server.hasAdminRights || hackDifficulty >= 100) return 0;
|
||||
const hackFactor = 1.75;
|
||||
const difficultyMult = (100 - hackDifficulty) / 100;
|
||||
const skillMult = clampNumber(hackFactor * person.skills.hacking, 1);
|
||||
const skillMult = utils.clampNumber(hackFactor * person.skills.hacking, 1);
|
||||
const skillChance = (skillMult - requiredHackingSkill) / skillMult;
|
||||
const chance =
|
||||
skillChance *
|
||||
difficultyMult *
|
||||
person.mults.hacking_chance *
|
||||
calculateIntelligenceBonus(person.skills.intelligence, 1);
|
||||
return clampNumber(chance, 0, 1);
|
||||
return utils.clampNumber(chance, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -79,8 +75,9 @@ function calculatePercentMoneyHacked(server: IServer, person: IPerson): number {
|
|||
return Math.min(1, Math.max(percentMoneyHacked, 0));
|
||||
}
|
||||
|
||||
/** Returns time it takes to complete a hack on a server, in seconds */
|
||||
/** Returns time it takes to complete a hack on a server, in milliseconds */
|
||||
function calculateHackingTime(server: IServer, person: IPerson): number {
|
||||
if (utils.isDarknetServer(server)) return 16;
|
||||
const { hackDifficulty, requiredHackingSkill } = server;
|
||||
if (typeof hackDifficulty !== "number" || typeof requiredHackingSkill !== "number") return Infinity;
|
||||
const difficultyMult = requiredHackingSkill * hackDifficulty;
|
||||
|
|
@ -98,17 +95,17 @@ function calculateHackingTime(server: IServer, person: IPerson): number {
|
|||
currentNodeMults.HackingSpeedMultiplier *
|
||||
calculateIntelligenceBonus(person.skills.intelligence, 1));
|
||||
|
||||
return hackingTime;
|
||||
return hackingTime * 1000;
|
||||
}
|
||||
|
||||
/** Returns time it takes to complete a grow operation on a server, in seconds */
|
||||
/** Returns time it takes to complete a grow operation on a server, in milliseconds */
|
||||
function calculateGrowTime(server: IServer, person: IPerson): number {
|
||||
const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2
|
||||
|
||||
return growTimeMultiplier * calculateHackingTime(server, person);
|
||||
}
|
||||
|
||||
/** Returns time it takes to complete a weaken operation on a server, in seconds */
|
||||
/** Returns time it takes to complete a weaken operation on a server, in milliseconds */
|
||||
function calculateWeakenTime(server: IServer, person: IPerson): number {
|
||||
const weakenTimeMultiplier = 4; // Relative to hacking time
|
||||
|
||||
|
|
@ -160,7 +157,7 @@ function calculateGrowMoney(server: IServer, p: IPerson, threads: number, cores
|
|||
// cap at max (or data corruption)
|
||||
if (
|
||||
server.moneyMax !== undefined &&
|
||||
isValidNumber(server.moneyMax) &&
|
||||
utils.isValidNumber(server.moneyMax) &&
|
||||
(moneyAvailable > server.moneyMax || isNaN(moneyAvailable))
|
||||
) {
|
||||
moneyAvailable = server.moneyMax;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { utils } from "@/utils/utils";
|
||||
import { Person as IPerson } from "@ns";
|
||||
import { currentNodeMults } from "./exports";
|
||||
import { CONSTANTS, log1point02, MaxFavor } from "./constants";
|
||||
import { currentNodeMults } from "./exports";
|
||||
import { Player } from "./player";
|
||||
import { clampNumber } from "@/utils/utils";
|
||||
|
||||
export const reputation = {
|
||||
favorToRep,
|
||||
|
|
@ -16,12 +16,12 @@ export const reputation = {
|
|||
|
||||
function favorToRep(f: number): number {
|
||||
// expm1 is e^x - 1, which is more accurate for small x than doing it the obvious way.
|
||||
return clampNumber(25000 * Math.expm1(log1point02 * f), 0);
|
||||
return utils.clampNumber(25000 * Math.expm1(log1point02 * f), 0);
|
||||
}
|
||||
|
||||
function repToFavor(r: number): number {
|
||||
// log1p is log(x + 1), which is more accurate for small x than doing it the obvious way.
|
||||
return clampNumber(Math.log1p(r / 25000) / log1point02, 0, MaxFavor);
|
||||
return utils.clampNumber(Math.log1p(r / 25000) / log1point02, 0, MaxFavor);
|
||||
}
|
||||
|
||||
function calculateFavorAfterResetting(favor: number, playerReputation: number) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { clampNumber } from "@/utils/utils";
|
||||
import { utils } from "@/utils/utils";
|
||||
|
||||
export const skills = {
|
||||
calculateSkill,
|
||||
|
|
@ -18,7 +18,7 @@ export function calculateSkill(exp: number, mult = 1): number {
|
|||
return 1;
|
||||
}
|
||||
const value = Math.floor(mult * (32 * Math.log(exp + 534.6) - 200));
|
||||
return clampNumber(value, 1);
|
||||
return utils.clampNumber(value, 1);
|
||||
}
|
||||
|
||||
function calculateExp(skill: number, mult = 1): number {
|
||||
|
|
@ -37,7 +37,7 @@ function calculateExp(skill: number, mult = 1): number {
|
|||
}
|
||||
value = newValue;
|
||||
}
|
||||
return clampNumber(value, 0);
|
||||
return utils.clampNumber(value, 0);
|
||||
}
|
||||
|
||||
function calculateSkillProgress(exp: number, mult = 1): ISkillProgress {
|
||||
|
|
@ -50,10 +50,10 @@ function calculateSkillProgress(exp: number, mult = 1): ISkillProgress {
|
|||
const normalize = (value: number): number => ((value - baseExperience) * 100) / (nextExperience - baseExperience);
|
||||
|
||||
const rawProgress = nextExperience - baseExperience !== 0 ? normalize(exp) : 99.99;
|
||||
const progress = clampNumber(rawProgress, 0, 100);
|
||||
const progress = utils.clampNumber(rawProgress, 0, 100);
|
||||
|
||||
const currentExperience = clampNumber(exp - baseExperience, 0);
|
||||
const remainingExperience = clampNumber(nextExperience - exp, 0);
|
||||
const currentExperience = utils.clampNumber(exp - baseExperience, 0);
|
||||
const remainingExperience = utils.clampNumber(nextExperience - exp, 0);
|
||||
|
||||
return {
|
||||
currentSkill,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { ezgame } from "@/ezgame";
|
||||
import { randomNumber } from "@/utils/utils";
|
||||
import { getNormalServer } from "@/utils/get-normal-server";
|
||||
import { utils } from "@/utils/utils";
|
||||
import { NS } from "@ns";
|
||||
|
||||
interface TestCase {
|
||||
|
|
@ -7,6 +8,12 @@ interface TestCase {
|
|||
fn: (ns: NS, serverName: string) => void;
|
||||
}
|
||||
|
||||
// the actual result sometimes has 1 - 2 extra decimal places compared to my implementation,
|
||||
// which causes tests to fail, so we round both results to 5 decimal places before comparing
|
||||
function roundTo5Decimals(num: number): number {
|
||||
return Math.round(num * 100000) / 100000;
|
||||
}
|
||||
|
||||
// add servers to be tested against here
|
||||
const serverNames: string[] = ["n00dles", "foodnstuff", "joesguns", "sigma-cosmetics", "max-hardware"];
|
||||
|
||||
|
|
@ -15,9 +22,9 @@ const gangTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "gang.ascensionMultiplier",
|
||||
fn: (ns, serverName) => {
|
||||
const points = randomNumber(0, 1e9);
|
||||
const testResult = ezgame.formulas.gang.ascensionMultiplier(points);
|
||||
const actualResult = ns.formulas.gang.ascensionMultiplier(points);
|
||||
const points = utils.randomNumber(0, 1e9);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.gang.ascensionMultiplier(points));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.gang.ascensionMultiplier(points));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -26,9 +33,9 @@ const gangTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "gang.ascensionPointsGain",
|
||||
fn: (ns, serverName) => {
|
||||
const exp = randomNumber(0, 1e9);
|
||||
const testResult = ezgame.formulas.gang.ascensionPointsGain(exp);
|
||||
const actualResult = ns.formulas.gang.ascensionPointsGain(exp);
|
||||
const exp = utils.randomNumber(0, 1e9);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.gang.ascensionPointsGain(exp));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.gang.ascensionPointsGain(exp));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -45,12 +52,12 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "hacking.growAmount",
|
||||
fn: (ns, serverName) => {
|
||||
const server = ns.getServer(serverName);
|
||||
const server = getNormalServer(ns, serverName);
|
||||
const player = ns.getPlayer();
|
||||
const threads = randomNumber(1, 100);
|
||||
const cores = randomNumber(1, 16);
|
||||
const testResult = ezgame.formulas.hacking.growAmount(server, player, threads, cores);
|
||||
const actualResult = ns.formulas.hacking.growAmount(server, player, threads, cores);
|
||||
const threads = utils.randomNumber(1, 100);
|
||||
const cores = utils.randomNumber(1, 16);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.hacking.growAmount(server, player, threads, cores));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.hacking.growAmount(server, player, threads, cores));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -59,12 +66,12 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "hacking.growPercent",
|
||||
fn: (ns, serverName) => {
|
||||
const server = ns.getServer(serverName);
|
||||
const threads = randomNumber(1, 100);
|
||||
const server = getNormalServer(ns, serverName);
|
||||
const threads = utils.randomNumber(1, 100);
|
||||
const player = ns.getPlayer();
|
||||
const cores = randomNumber(1, 16);
|
||||
const testResult = ezgame.formulas.hacking.growPercent(server, threads, player, cores);
|
||||
const actualResult = ns.formulas.hacking.growPercent(server, threads, player, cores);
|
||||
const cores = utils.randomNumber(1, 16);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.hacking.growPercent(server, threads, player, cores));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.hacking.growPercent(server, threads, player, cores));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -73,14 +80,14 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "hacking.growThreads",
|
||||
fn: (ns, serverName) => {
|
||||
const server = ns.getServer(serverName);
|
||||
const server = getNormalServer(ns, serverName);
|
||||
const player = ns.getPlayer();
|
||||
// if moneyMax is not set, use a large number to ensure growThreads returns a valid number of threads
|
||||
// anyways if it is above moneyMax, the function should clamp it to the max (hopefully)
|
||||
const targetMoney = server.moneyMax ?? 1e120;
|
||||
const cores = randomNumber(1, 16);
|
||||
const testResult = ezgame.formulas.hacking.growThreads(server, player, targetMoney, cores);
|
||||
const actualResult = ns.formulas.hacking.growThreads(server, player, targetMoney, cores);
|
||||
const cores = utils.randomNumber(1, 16);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.hacking.growThreads(server, player, targetMoney, cores));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.hacking.growThreads(server, player, targetMoney, cores));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -89,10 +96,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "hacking.growTime",
|
||||
fn: (ns, serverName) => {
|
||||
const server = ns.getServer(serverName);
|
||||
const server = getNormalServer(ns, serverName);
|
||||
const player = ns.getPlayer();
|
||||
const testResult = ezgame.formulas.hacking.growTime(server, player);
|
||||
const actualResult = ns.formulas.hacking.growTime(server, player);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.hacking.growTime(server, player));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.hacking.growTime(server, player));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -101,10 +108,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "hacking.hackChance",
|
||||
fn: (ns, serverName) => {
|
||||
const server = ns.getServer(serverName);
|
||||
const server = getNormalServer(ns, serverName);
|
||||
const player = ns.getPlayer();
|
||||
const testResult = ezgame.formulas.hacking.hackChance(server, player);
|
||||
const actualResult = ns.formulas.hacking.hackChance(server, player);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.hacking.hackChance(server, player));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.hacking.hackChance(server, player));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -113,10 +120,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "hacking.hackExp",
|
||||
fn: (ns, serverName) => {
|
||||
const server = ns.getServer(serverName);
|
||||
const server = getNormalServer(ns, serverName);
|
||||
const player = ns.getPlayer();
|
||||
const testResult = ezgame.formulas.hacking.hackExp(server, player);
|
||||
const actualResult = ns.formulas.hacking.hackExp(server, player);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.hacking.hackExp(server, player));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.hacking.hackExp(server, player));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -125,10 +132,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "hacking.hackPercent",
|
||||
fn: (ns, serverName) => {
|
||||
const server = ns.getServer(serverName);
|
||||
const server = getNormalServer(ns, serverName);
|
||||
const player = ns.getPlayer();
|
||||
const testResult = ezgame.formulas.hacking.hackPercent(server, player);
|
||||
const actualResult = ns.formulas.hacking.hackPercent(server, player);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.hacking.hackPercent(server, player));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.hacking.hackPercent(server, player));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -137,10 +144,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "hacking.hackTime",
|
||||
fn: (ns, serverName) => {
|
||||
const server = ns.getServer(serverName);
|
||||
const server = getNormalServer(ns, serverName);
|
||||
const player = ns.getPlayer();
|
||||
const testResult = ezgame.formulas.hacking.hackTime(server, player);
|
||||
const actualResult = ns.formulas.hacking.hackTime(server, player);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.hacking.hackTime(server, player));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.hacking.hackTime(server, player));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
@ -149,10 +156,10 @@ const hackingTests = (ns: NS, serverName: string): TestCase[] => [
|
|||
{
|
||||
name: "hacking.weakenTime",
|
||||
fn: (ns, serverName) => {
|
||||
const server = ns.getServer(serverName);
|
||||
const server = getNormalServer(ns, serverName);
|
||||
const player = ns.getPlayer();
|
||||
const testResult = ezgame.formulas.hacking.weakenTime(server, player);
|
||||
const actualResult = ns.formulas.hacking.weakenTime(server, player);
|
||||
const testResult = roundTo5Decimals(ezgame.formulas.hacking.weakenTime(server, player));
|
||||
const actualResult = roundTo5Decimals(ns.formulas.hacking.weakenTime(server, player));
|
||||
if (testResult !== actualResult) {
|
||||
throw new Error(`expected ${actualResult}, got ${testResult}`);
|
||||
}
|
||||
|
|
|
|||
12
src/test.ts
12
src/test.ts
|
|
@ -1,11 +1,9 @@
|
|||
import { NS } from "@ns";
|
||||
import { NS, Server } from "@ns";
|
||||
import { ezgame } from "./ezgame";
|
||||
import { scan } from "./utils/scan";
|
||||
import { getNormalServer } from "./utils/get-normal-server";
|
||||
|
||||
export const main = (ns: NS) => {
|
||||
const server = ns.getServer("n00dles");
|
||||
const player = ns.getPlayer();
|
||||
const testResult = ezgame.formulas.hacking.growTime(server, player);
|
||||
const actualResult = ns.formulas.hacking.growTime(server, player);
|
||||
console.log(testResult);
|
||||
console.log(actualResult);
|
||||
// console.log(ns.formulas.hacking.growTime(getNormalServer(ns, "n00dles"), ns.getPlayer()));
|
||||
console.log(ns.getServer("n00dles"));
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,8 +11,15 @@ interface ServerAnalysis {
|
|||
|
||||
export const analyze = (ns: NS, hostnames: string[]) => {
|
||||
hostnames.forEach((hostname) => {
|
||||
// skip darknet servers
|
||||
if (ns.dnet.isDarknetServer(hostname)) {
|
||||
ns.tprint(`Skipping darknet server: ${hostname}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the server object for the hostname
|
||||
const server: Server = ns.getServer(hostname);
|
||||
const server = ns.getServer(hostname) as Server;
|
||||
|
||||
// create a new object that matches the ServerAnalysis interface
|
||||
const analysis: ServerAnalysis = {
|
||||
hostname: server.hostname,
|
||||
|
|
@ -21,6 +28,8 @@ export const analyze = (ns: NS, hostnames: string[]) => {
|
|||
portsRequiredForNuke: server.numOpenPortsRequired ?? 0,
|
||||
maxRam: server.maxRam,
|
||||
};
|
||||
|
||||
ns.tprint(analysis);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
9
src/utils/get-normal-server.ts
Normal file
9
src/utils/get-normal-server.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { NS, Server } from "@ns";
|
||||
|
||||
export function getNormalServer(ns: NS, hostname: string): Server {
|
||||
if (ns.dnet.isDarknetServer(hostname)) {
|
||||
throw new Error(`Server ${hostname} is a darknet server`);
|
||||
}
|
||||
|
||||
return ns.getServer(hostname) as Server;
|
||||
}
|
||||
|
|
@ -1,29 +1,23 @@
|
|||
import { NS } from '@ns';
|
||||
import { NS } from "@ns";
|
||||
|
||||
export const serverBuyMax = (ns: NS, serverNamePrefix: string) => {
|
||||
// get the maximum number of servers that can be purchased
|
||||
const maxServers = ns.getPurchasedServerLimit();
|
||||
const maxServers = ns.cloud.getServerLimit();
|
||||
|
||||
// get the number of servers currently owned
|
||||
const currentServers = ns.getPurchasedServers().length;
|
||||
const currentServers = ns.cloud.getServerNames().length;
|
||||
|
||||
// calculate the number of servers that can still be purchased
|
||||
const serversToPurchase = maxServers - currentServers;
|
||||
|
||||
// if we can't buy any more servers, return
|
||||
if (serversToPurchase <= 0) {
|
||||
ns.tprint('Cannot purchase any more servers. Maximum limit reached.');
|
||||
ns.tprint("Cannot purchase any more servers. Maximum limit reached.");
|
||||
return;
|
||||
}
|
||||
|
||||
// get current money available
|
||||
const moneyAvailable = ns.getServerMoneyAvailable('home');
|
||||
|
||||
// smallest ram we can buy is 2gb, check if can even afford that
|
||||
if (moneyAvailable < ns.getPurchasedServerCost(2)) {
|
||||
ns.tprint('Nigga you broke, not enough money to buy the smallest server');
|
||||
return;
|
||||
}
|
||||
const moneyAvailable = ns.getServerMoneyAvailable("home");
|
||||
|
||||
// find the maximum ram we can afford spread out over the number of servers we can buy
|
||||
// the ram amount that can be bought is in power of 2
|
||||
|
|
@ -35,7 +29,7 @@ export const serverBuyMax = (ns: NS, serverNamePrefix: string) => {
|
|||
// calculate the ram based on power
|
||||
const ram = Math.pow(2, pow);
|
||||
// get the cost of the server with the ram
|
||||
const totalCost = ns.getPurchasedServerCost(ram) * serversToPurchase;
|
||||
const totalCost = ns.cloud.getServerCost(ram) * serversToPurchase;
|
||||
|
||||
// check if can buy
|
||||
if (totalCost <= moneyAvailable) {
|
||||
|
|
@ -47,13 +41,19 @@ export const serverBuyMax = (ns: NS, serverNamePrefix: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
// check if we found a valid target ram amount
|
||||
if (targetRam < 2) {
|
||||
ns.tprint("Unable to find affordable server configuration. Try buying fewer servers.");
|
||||
return;
|
||||
}
|
||||
|
||||
// now buy the servers with the target ram
|
||||
let serversPurchased = 0;
|
||||
while (serversPurchased < serversToPurchase) {
|
||||
const serverName = `${serverNamePrefix}-${currentServers + serversPurchased + 1}`;
|
||||
|
||||
if (!ns.serverExists(serverName)) {
|
||||
ns.purchaseServer(serverName, targetRam);
|
||||
ns.cloud.purchaseServer(serverName, targetRam);
|
||||
serversPurchased++;
|
||||
}
|
||||
}
|
||||
|
|
@ -63,6 +63,6 @@ export const serverBuyMax = (ns: NS, serverNamePrefix: string) => {
|
|||
};
|
||||
|
||||
export const main = (ns: NS) => {
|
||||
const serverNamePrefix = 'worker';
|
||||
const serverNamePrefix = "worker";
|
||||
serverBuyMax(ns, serverNamePrefix);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { NS } from '@ns';
|
||||
import { kill } from '../kill';
|
||||
import { NS } from "@ns";
|
||||
import { kill } from "../kill";
|
||||
|
||||
export const serverDeleteAll = (ns: NS) => {
|
||||
// get a list of all the purchased servers
|
||||
const serverNames: string[] = ns.getPurchasedServers();
|
||||
const serverNames: string[] = ns.cloud.getServerNames();
|
||||
|
||||
// initialize a counter for total cost of all the servers
|
||||
let totalCost = 0;
|
||||
|
|
@ -14,14 +14,14 @@ export const serverDeleteAll = (ns: NS) => {
|
|||
const ram = ns.getServerMaxRam(serverName);
|
||||
|
||||
// calculate the cost of the server and add it to the total cost
|
||||
const cost = ns.getPurchasedServerCost(ram);
|
||||
const cost = ns.cloud.getServerCost(ram);
|
||||
totalCost += cost;
|
||||
|
||||
// kill all the processes running on the server before removing it
|
||||
kill(ns, serverName);
|
||||
|
||||
// remove the server
|
||||
ns.deleteServer(serverName);
|
||||
ns.cloud.deleteServer(serverName);
|
||||
});
|
||||
|
||||
ns.tprint(`Purchased servers deleted: ${serverNames.length}`);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,25 @@
|
|||
import { Server } from "@ns";
|
||||
|
||||
export const utils = {
|
||||
utilityFormatDate,
|
||||
utilityFormatSize,
|
||||
utilityUnformatSize,
|
||||
utilityExtractFilename,
|
||||
clampNumber,
|
||||
clampInteger,
|
||||
isValidNumber,
|
||||
randomNumber,
|
||||
randomInteger,
|
||||
isDarknetServer,
|
||||
};
|
||||
|
||||
/**
|
||||
* Format the date/time.
|
||||
* If the date is today, show the time. Otherwise, show the date in "day month year" format.
|
||||
* @param dateString The date string to format
|
||||
* @returns Formatted date/time string
|
||||
*/
|
||||
export const utilityFormatDate = (dateString: string): string => {
|
||||
function utilityFormatDate(dateString: string): string {
|
||||
const date = new Date(dateString);
|
||||
const today = new Date();
|
||||
|
||||
|
|
@ -22,14 +37,14 @@ export const utilityFormatDate = (dateString: string): string => {
|
|||
// "day month year" format
|
||||
return date.toLocaleDateString(undefined, { day: "numeric", month: "long", year: "numeric" });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Format bytes into human-readable size
|
||||
* @param bytes Number of bytes to format
|
||||
* @returns Formatted size string
|
||||
*/
|
||||
export const utilityFormatSize = (bytes: number): string => {
|
||||
function utilityFormatSize(bytes: number): string {
|
||||
if (bytes === 0) return "0 Bytes";
|
||||
|
||||
const k = 1024;
|
||||
|
|
@ -38,19 +53,19 @@ export const utilityFormatSize = (bytes: number): string => {
|
|||
|
||||
// tf is pow
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a formatted size string back to bytes
|
||||
* @param formattedSize Formatted size string (must be in the same format produced by `utilityFormatSize()`)
|
||||
* @returns Number of bytes
|
||||
*/
|
||||
export const utilityUnformatSize = (formattedSize: string): number => {
|
||||
function utilityUnformatSize(formattedSize: string): number {
|
||||
const sizes = ["Bytes", "KB", "MB", "GB"];
|
||||
const [value, unit] = formattedSize.split(" ");
|
||||
const index = sizes.indexOf(unit);
|
||||
return parseFloat(value) * Math.pow(1024, index);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract filename stem and extension from a file path
|
||||
|
|
@ -58,7 +73,7 @@ export const utilityUnformatSize = (formattedSize: string): number => {
|
|||
* @returns Object containing `fileStem` and `fileExtension`. `fileStem` is the filename without the extension, and `fileExtension` is the extension in lowercase (or an empty string if there is no extension).
|
||||
* @throws Error if the file path is invalid
|
||||
*/
|
||||
export const utilityExtractFilename = (filePath: string): { fileStem: string; fileExtension: string } | null => {
|
||||
function utilityExtractFilename(filePath: string): { fileStem: string; fileExtension: string } | null {
|
||||
const lastSlashIndex = filePath.lastIndexOf("/");
|
||||
const lastDotIndex = filePath.lastIndexOf(".");
|
||||
|
||||
|
|
@ -86,7 +101,7 @@ export const utilityExtractFilename = (filePath: string): { fileStem: string; fi
|
|||
}
|
||||
|
||||
return { fileStem: fileStem, fileExtension: fileExtension };
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamps a value to a lower and upper bound
|
||||
|
|
@ -95,7 +110,7 @@ export const utilityExtractFilename = (filePath: string): { fileStem: string; fi
|
|||
* @param max Upper bound, defaults to `Number.MAX_VALUE`
|
||||
* @returns Clamped value
|
||||
*/
|
||||
export function clampNumber(value: number, min: number = -Number.MAX_VALUE, max: number = Number.MAX_VALUE): number {
|
||||
function clampNumber(value: number, min: number = -Number.MAX_VALUE, max: number = Number.MAX_VALUE): number {
|
||||
if (isNaN(value)) {
|
||||
// if (CONSTANTS.isDevBranch) throw new Error("NaN passed into clampNumber()");
|
||||
return min;
|
||||
|
|
@ -110,7 +125,7 @@ export function clampNumber(value: number, min: number = -Number.MAX_VALUE, max:
|
|||
* @param max Upper bound, defaults to `Number.MAX_SAFE_INTEGER`
|
||||
* @returns Clamped integer value
|
||||
*/
|
||||
export function clampInteger(
|
||||
function clampInteger(
|
||||
value: number,
|
||||
min: number = -Number.MAX_SAFE_INTEGER,
|
||||
max: number = Number.MAX_SAFE_INTEGER,
|
||||
|
|
@ -128,7 +143,7 @@ export function clampInteger(
|
|||
* @param n The number to check
|
||||
* @returns True if n is a valid number, false otherwise
|
||||
*/
|
||||
export function isValidNumber(n: number): boolean {
|
||||
function isValidNumber(n: number): boolean {
|
||||
return typeof n === "number" && !isNaN(n);
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +153,7 @@ export function isValidNumber(n: number): boolean {
|
|||
* @param max Maximum value (inclusive)
|
||||
* @returns Random number between min and max
|
||||
*/
|
||||
export function randomNumber(min: number, max: number): number {
|
||||
function randomNumber(min: number, max: number): number {
|
||||
if (min > max) throw new Error("min cannot be greater than max");
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
|
@ -149,6 +164,10 @@ export function randomNumber(min: number, max: number): number {
|
|||
* @param max Maximum value (inclusive)
|
||||
* @returns Random integer between min and max
|
||||
*/
|
||||
export function randomInteger(min: number, max: number): number {
|
||||
function randomInteger(min: number, max: number): number {
|
||||
return Math.floor(randomNumber(min, max + 1));
|
||||
}
|
||||
|
||||
function isDarknetServer(server: Server): server is Server & { isStationary: boolean } {
|
||||
return "isStationary" in server;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue