f
This commit is contained in:
parent
374196acce
commit
48771f54dd
46
src/auto-backdoor.ts
Normal file
46
src/auto-backdoor.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { NS } from '@ns'
|
||||
import { parse } from './lib/flag';
|
||||
import { sprintf } from './lib/printf';
|
||||
import { selectRootedServerList } from "./lib/servers"
|
||||
|
||||
|
||||
async function propagateBackdoor(ns:NS, hostname: string): Promise<void>{
|
||||
ns.singularity.connect(hostname);
|
||||
const list = ns.scan(hostname);
|
||||
for (const relname of list) {
|
||||
const info = ns.getServer(relname);
|
||||
if(info.backdoorInstalled){
|
||||
continue;
|
||||
}
|
||||
if(info.requiredHackingSkill > ns.getHackingLevel()){
|
||||
continue;
|
||||
}
|
||||
ns.tprint(`install backdoor ${relname}`);
|
||||
ns.singularity.connect(relname);
|
||||
await ns.singularity.installBackdoor();
|
||||
ns.singularity.connect(hostname);
|
||||
}
|
||||
}
|
||||
|
||||
export async function main(ns: NS) : Promise<void> {
|
||||
const flag = parse(ns.args.map(x=>x.toString()));
|
||||
if(flag.h || flag.help){
|
||||
const msg = ['run cmd']
|
||||
msg.forEach(x=>ns.tprint(x));
|
||||
return;
|
||||
}
|
||||
if(flag._.length === 0){
|
||||
const servers = selectRootedServerList(ns);
|
||||
for(const server of servers){
|
||||
ns.tprint("prop backdoor to "+server.hostname);
|
||||
await propagateBackdoor(ns,server.hostname);
|
||||
}
|
||||
}
|
||||
else{
|
||||
// const hostname = flag._[0];
|
||||
// ns.tprint(sprintf("install backdoor %s",hostname));
|
||||
// await ns.singularity.installBackdoor(hostname);
|
||||
// ns.tprint("done");
|
||||
}
|
||||
}
|
||||
|
@ -20,14 +20,19 @@ export async function main(ns: NS) : Promise<void> {
|
||||
return;
|
||||
}
|
||||
const v = parseInt(flag._[0].toString());
|
||||
if(isNaN(v)){
|
||||
ns.tprint("Error. Require Integer. v = " + flag._[0]);
|
||||
return;
|
||||
}
|
||||
const hostname = flag.host ?? flag.t;
|
||||
const server = ns.getServer(hostname)
|
||||
if(flag.graph){
|
||||
const col = [];
|
||||
for (let i = 1; i < v; i++) {
|
||||
const info = calculateBatchResource(ns,hostname,i,server.moneyMax,1);
|
||||
if(info === null) break;
|
||||
col.push({
|
||||
costEffect :(info.earnMoneyPerSec / info.totalThreadCount),
|
||||
costEffect :(info.earnMoneyPerCycle / info.totalThreadCount),
|
||||
index: i,
|
||||
total: info.totalThreadCount
|
||||
})
|
||||
|
@ -1,13 +1,15 @@
|
||||
import { NS, AutocompleteData } from '@ns'
|
||||
import { installBatchFilePack, isBatchFilePackInstalled, scpBatchFilePack } from './lib/batchbase';
|
||||
import { installBatchFilePack, isBatchFilePackInstalled, scpBatchFilePack, batchDaemon, requestHWGW } from './lib/batchbase';
|
||||
import { parse } from './lib/flag';
|
||||
|
||||
|
||||
function help(ns:NS):void{
|
||||
ns.tprint("run cmd [target(hostname)] -h hostname")
|
||||
ns.tprint("run cmd [target(hostname)] --hostname hostname")
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
export async function main(ns : NS) : Promise<void> {
|
||||
|
||||
const flag = parse(ns.args.map(String))
|
||||
|
||||
const hostname: string|undefined = flag.hostname ?? flag.n;
|
||||
@ -22,15 +24,20 @@ export async function main(ns : NS) : Promise<void> {
|
||||
return;
|
||||
}
|
||||
const target = flag._[0].toString();
|
||||
|
||||
ns.print("check batch file pack ...")
|
||||
if(!isBatchFilePackInstalled(ns)){
|
||||
await installBatchFilePack(ns);
|
||||
}
|
||||
|
||||
const server = ns.getServer(hostname)
|
||||
await scpBatchFilePack(ns,hostname);
|
||||
|
||||
const server = ns.getServer(target);
|
||||
ns.tprint();
|
||||
ns.print("request hwgw ...")
|
||||
requestHWGW({
|
||||
hostname,
|
||||
usableRam: server.maxRam - server.ramUsed,
|
||||
},target);
|
||||
ns.print("request hwgw done")
|
||||
ns.print("start batch daemon ...");
|
||||
await batchDaemon(ns, target);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
@ -21,7 +21,7 @@ export async function main(ns: NS): Promise<void> {
|
||||
nThread = th;
|
||||
}
|
||||
else {
|
||||
nThread = calculateMaximumThread(ns, hostname, getRamOfScript(ns,"weakenLoop"));
|
||||
nThread = calculateMaximumThread(ns, hostname, ns.getScriptRam("share-server.js",hostname));
|
||||
}
|
||||
const pid = ns.exec("share-server.js",hostname, nThread);
|
||||
ns.tprint(pid," Process started.");
|
||||
|
16
src/get-my-karma.ts
Normal file
16
src/get-my-karma.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { NS } from '@ns'
|
||||
import { parse } from './lib/flag';
|
||||
import { sprintf } from './lib/printf';
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
export async function main(ns: NS) : Promise<void> {
|
||||
const flag = parse(ns.args.map(x=>x.toString()));
|
||||
if(flag.h || flag.help){
|
||||
const msg = ['run cmd']
|
||||
msg.forEach(x=>ns.tprint(x));
|
||||
return;
|
||||
}
|
||||
// typescript error ignore
|
||||
// @ts-ignore TS2339
|
||||
ns.tprint(sprintf("karma: %.3f",ns.heart.break()));
|
||||
}
|
46
src/growing.ts
Normal file
46
src/growing.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { NS, AutocompleteData } from '@ns'
|
||||
import { installBatchFilePack, isBatchFilePackInstalled, scpBatchFilePack, growDaemon, requestGrow } from './lib/batchbase';
|
||||
import { parse } from './lib/flag';
|
||||
|
||||
|
||||
function help(ns:NS):void{
|
||||
ns.tprint("run cmd [target(hostname)] --hostname hostname")
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
export async function main(ns : NS) : Promise<void> {
|
||||
const flag = parse(ns.args.map(String))
|
||||
|
||||
const hostname: string|undefined = flag.hostname ?? flag.n;
|
||||
if(!hostname){
|
||||
ns.tprint("hostname is not set");
|
||||
help(ns);
|
||||
return;
|
||||
}
|
||||
if(flag._.length == 0){
|
||||
ns.tprint("target is not set");
|
||||
help(ns);
|
||||
return;
|
||||
}
|
||||
const target = flag._[0].toString();
|
||||
ns.print("check batch file pack ...")
|
||||
if(!isBatchFilePackInstalled(ns)){
|
||||
await installBatchFilePack(ns);
|
||||
}
|
||||
const server = ns.getServer(hostname)
|
||||
await scpBatchFilePack(ns,hostname);
|
||||
ns.print("request hwgw ...")
|
||||
requestGrow({
|
||||
hostname,
|
||||
usableRam: server.maxRam - server.ramUsed,
|
||||
},target);
|
||||
ns.print("request hwgw done")
|
||||
ns.print("start batch daemon ...");
|
||||
await growDaemon(ns, target);
|
||||
ns.print("end grow daemon");
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export function autocomplete(data : AutocompleteData, args : string[]) : string[] {
|
||||
return [...data.servers]
|
||||
}
|
@ -225,11 +225,11 @@ export async function main(ns: NS): Promise<void> {
|
||||
|
||||
const account = new Account(budget);
|
||||
ns.tail();
|
||||
const period = 1000;
|
||||
const period = 100;
|
||||
for (let i = 0; i < iter; i++) {
|
||||
//ns.clearLog()
|
||||
cycle(ns, account);
|
||||
await ns.sleep(period);
|
||||
account.upgradeIncrement(ns,rate,period);
|
||||
account.upgradeIncrement(ns,rate*0.1,period);
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import { NS, Server } from "@ns"
|
||||
import { info } from "console";
|
||||
import { calculateServerGrowth, FormulaHelper } from "./formula";
|
||||
|
||||
import { Scheduler } from "./scheduler";
|
||||
|
||||
export type BatchType = "hack" | "grow" | "weaken" | "weakenLoop";
|
||||
|
||||
@ -104,6 +105,7 @@ export interface ExecOption {
|
||||
*/
|
||||
numThread?: number;
|
||||
/**
|
||||
* milliseconds to sleep before exec
|
||||
* @default 0
|
||||
*/
|
||||
sleepDuration?: number;
|
||||
@ -115,8 +117,9 @@ export interface ExecOption {
|
||||
}
|
||||
|
||||
function execBatchfile(ns: NS, path: string, option: ExecOption): number {
|
||||
const uuid = crypto.randomUUID();
|
||||
return ns.exec(path, option.hostname, option.numThread,
|
||||
option.sleepDuration ?? 0, option.target, option.stock ?? false);
|
||||
option.sleepDuration ?? 0, option.target, option.stock ?? false, uuid);
|
||||
}
|
||||
|
||||
export function execHack(ns: NS, option: ExecOption): number {
|
||||
@ -131,16 +134,13 @@ export function execWeaken(ns: NS, option: ExecOption): number {
|
||||
export function execWeakenLoop(ns: NS, option: ExecOption): number {
|
||||
return execBatchfile(ns, "/tmp/weakenLoop.js", option);
|
||||
}
|
||||
export function execScriptOf(ns: NS,type: BatchType, option:ExecOption):number {
|
||||
return execBatchfile(ns, "/tmp/" + type + ".js", option);
|
||||
}
|
||||
export function getRamOfScript(ns: NS, type: BatchType): number{
|
||||
return batchFilePack.filter(x=>x.type == type)[0].ram;
|
||||
}
|
||||
|
||||
//type BatchType = "hack" | "grow" | "weaken";
|
||||
//
|
||||
//type Batch = {
|
||||
// type: BatchType;
|
||||
// options: ExecOption;
|
||||
//}
|
||||
type ReserveRequest = {
|
||||
hostname: string;
|
||||
usableRam: number;
|
||||
@ -156,83 +156,30 @@ interface HWGW {
|
||||
GWThreadCount: number;
|
||||
}
|
||||
|
||||
type WorkReserved = {
|
||||
allocated:false;
|
||||
} | {
|
||||
allocated:true;
|
||||
hwgw: HWGW;
|
||||
};
|
||||
function getTotalRamOf(hwgw: HWGW): number{
|
||||
return hwgw.HThreadCount * 1.7 + hwgw.HWThreadCount * 1.75 + hwgw.GThreadCount * 1.75 + hwgw.GWThreadCount * 1.75;
|
||||
}
|
||||
|
||||
type Resource = {
|
||||
hostname: string;
|
||||
usableRam: string;
|
||||
usableRam: number;
|
||||
};
|
||||
|
||||
class HWGWBatchManager {
|
||||
willExecuted: WorkReserved[];
|
||||
server: Server;
|
||||
ns: NS;
|
||||
createdAt: number;
|
||||
|
||||
|
||||
constructor(ns: NS, hostname: string) {
|
||||
this.ns = ns;
|
||||
this.willExecuted = [];
|
||||
this.server = ns.getServer(hostname);
|
||||
this.createdAt = ns.getTimeSinceLastAug();
|
||||
|
||||
this.growArray();
|
||||
}
|
||||
private popRequest(): ReserveRequest[]{
|
||||
const key = getKeyOfHWGWBatchManager(this.server.hostname);
|
||||
const text = localStorage.getItem(key)
|
||||
if(text === null){
|
||||
return [];
|
||||
}
|
||||
localStorage.setItem(key,"");
|
||||
return JSON.parse(text) as ReserveRequest[];
|
||||
}
|
||||
private growArray(n: number): void {
|
||||
while (this.willExecuted.length <= n) {
|
||||
this.willExecuted.push({
|
||||
allocated:false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
reserveBatch(time: number): void {
|
||||
const milli = time - this.ns.getTimeSinceLastAug();
|
||||
const sec = Math.floor(milli / 1000);
|
||||
this.growArray(sec);
|
||||
this.willExecuted[sec] = true;
|
||||
}
|
||||
async tick(): Promise<void> {
|
||||
const data = this.willExecuted.shift();
|
||||
await this.sleepCorrect();
|
||||
}
|
||||
/**
|
||||
* exact time Sleep
|
||||
*/
|
||||
async sleepCorrect(): Promise<void> {
|
||||
const cur = this.ns.getTimeSinceLastAug();
|
||||
const sliceTime = 250;
|
||||
const delta = (cur - this.createdAt + sliceTime/2) % sliceTime - sliceTime/2;
|
||||
await this.ns.sleep(sliceTime - delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface HackCalculation extends HWGW {
|
||||
earnMoneyPerSec: number;
|
||||
earnExpPerSec: number;
|
||||
earnMoneyPerCycle: number;
|
||||
earnExpPerCycle: number;
|
||||
/**
|
||||
* cycle time in seconds.
|
||||
* cycle time in milliseconds.
|
||||
*/
|
||||
cycleTime: number;
|
||||
totalThreadCount: number;
|
||||
|
||||
weakenTime: number;
|
||||
growTime: number;
|
||||
hackTime: number;
|
||||
}
|
||||
|
||||
export function calculateBatchResource(ns: NS, hostname: string, hackThread: number, startMoney?: number, cores = 1): HackCalculation {
|
||||
export function calculateBatchResource(ns: NS, hostname: string, hackThread: number, startMoney?: number, cores = 1): HackCalculation| null {
|
||||
const helper = new FormulaHelper(ns);
|
||||
const server = ns.getServer(hostname);
|
||||
startMoney ??= server.moneyMax;
|
||||
@ -242,13 +189,14 @@ export function calculateBatchResource(ns: NS, hostname: string, hackThread: num
|
||||
const hackingChance = helper.calculateHackingChance(server);
|
||||
const earnMoneyPerCycle = hackThread * percentMoneyHacked * startMoney * hackingChance;
|
||||
const earnExpPerCycle = helper.calculateHackingExpGain(server) * hackThread * hackingChance;
|
||||
const cycleTime = 1 + helper.calculateWeakenTime(server);
|
||||
|
||||
const cycleTime = 1000 + helper.calculateWeakenTime(server);
|
||||
const increasedSecurityAfterHack = helper.calculateHackSecurity(hackThread) + server.minDifficulty;
|
||||
const nWeakenHackThreads = Math.ceil(helper.calculateWeakenThreadCountToTargetSecurity(
|
||||
server.minDifficulty,
|
||||
increasedSecurityAfterHack, cores));
|
||||
|
||||
if(startMoney <= earnMoneyPerCycle){
|
||||
return null;
|
||||
}
|
||||
const nGrowThreads = Math.ceil(helper.calculateGrowThreadCount(hostname, startMoney - earnMoneyPerCycle, startMoney, cores));
|
||||
const increasedSecurityAfterGrow = helper.calculuateGrowthSecurity(nGrowThreads, cores) + server.minDifficulty;
|
||||
|
||||
@ -257,8 +205,11 @@ export function calculateBatchResource(ns: NS, hostname: string, hackThread: num
|
||||
increasedSecurityAfterGrow, cores));
|
||||
|
||||
return {
|
||||
earnMoneyPerSec: earnMoneyPerCycle / cycleTime,
|
||||
earnExpPerSec: earnExpPerCycle / cycleTime,
|
||||
weakenTime: helper.calculateWeakenTime(server),
|
||||
growTime: helper.calculateGrowTime(server),
|
||||
hackTime: helper.calculateHackingTime(server),
|
||||
earnMoneyPerCycle,
|
||||
earnExpPerCycle,
|
||||
cycleTime,
|
||||
totalThreadCount: hackThread + nWeakenHackThreads + nGrowThreads + nWeakenGrowThreads,
|
||||
HThreadCount: hackThread,
|
||||
@ -267,14 +218,163 @@ export function calculateBatchResource(ns: NS, hostname: string, hackThread: num
|
||||
GWThreadCount: nWeakenGrowThreads
|
||||
}
|
||||
}
|
||||
class BatchManager {
|
||||
server: Server;
|
||||
ns: NS;
|
||||
totalRam: number
|
||||
scheluder: Scheduler;
|
||||
resources: Resource[] = [];
|
||||
|
||||
function calculateOptimal(ns: NS, target: string, req: ReserveRequest): HWGW {
|
||||
constructor(ns: NS, hostname: string) {
|
||||
this.ns = ns;
|
||||
this.server = ns.getServer(hostname);
|
||||
this.totalRam = 0;
|
||||
this.scheluder = new Scheduler(ns, 250);
|
||||
}
|
||||
|
||||
return {
|
||||
GThreadCount: 0,
|
||||
HThreadCount: 0,
|
||||
GWThreadCount: 0,
|
||||
HWThreadCount: 0,
|
||||
reserve(hostname: string, usableRam: number): void {
|
||||
this.resources.push({
|
||||
hostname,
|
||||
usableRam,
|
||||
});
|
||||
this.totalRam += usableRam;
|
||||
}
|
||||
|
||||
getUsableTotalRam(): number {
|
||||
return this.resources.reduce((acc, cur) => acc + cur.usableRam, 0);
|
||||
}
|
||||
|
||||
execute(type: BatchType, opt: Omit<ExecOption, "hostname">): number[] {
|
||||
const ret = [];
|
||||
let numThread = opt.numThread ?? 1;
|
||||
const ramUnit = getRamOfScript(this.ns, type);
|
||||
for (let i = 0; i < this.resources.length; i++) {
|
||||
const resource = this.resources[i]
|
||||
let threadToRun = Math.floor(resource.usableRam / ramUnit);
|
||||
if (threadToRun > numThread) {
|
||||
threadToRun = numThread;
|
||||
}
|
||||
if (threadToRun <= 0) continue;
|
||||
|
||||
const pid = execScriptOf(this.ns, type, {
|
||||
hostname: resource.hostname,
|
||||
numThread: threadToRun,
|
||||
sleepDuration: opt.sleepDuration,
|
||||
target: opt.target,
|
||||
stock: opt.stock,
|
||||
});
|
||||
resource.usableRam -= threadToRun * ramUnit;
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
const doWork = ()=>{
|
||||
resource.usableRam += threadToRun * ramUnit;
|
||||
const msg = [
|
||||
`${pid} has finished.`,
|
||||
`${resource.hostname} recover ${threadToRun * ramUnit} ram`]
|
||||
this.ns.print(msg.join("\n"));
|
||||
}
|
||||
this.scheluder.onPidTerminate(pid, {work() {doWork();}});
|
||||
numThread -= threadToRun;
|
||||
ret.push(pid);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
class HWGWBatchManager extends BatchManager {
|
||||
constructor(ns: NS, hostname: string) {
|
||||
super(ns, hostname);
|
||||
}
|
||||
|
||||
calcBatchResource(hackThread: number): HackCalculation| null {
|
||||
return calculateBatchResource(this.ns, this.server.hostname, hackThread, this.server.moneyMax)
|
||||
}
|
||||
/**
|
||||
* execute batch
|
||||
* do not await this function.
|
||||
* @param hwgw HackCalculation of HWGW
|
||||
* @param stock if true, it influnces stock market.
|
||||
* @returns set of pids of scripts runned.
|
||||
*/
|
||||
async execBatch(hwgw: HackCalculation, stock?: boolean): Promise<number[]> {
|
||||
stock ??= false;
|
||||
//this.ns.print(`executing batch of ${hwgw.totalThreadCount} threads.`);
|
||||
//this.ns.print(`total ram: ${this.totalRam}`);
|
||||
|
||||
this.ns.print(`stage 1: executed ${hwgw.HThreadCount} threads.`);
|
||||
const hpid = this.execute("hack",{
|
||||
target:this.server.hostname,
|
||||
numThread:hwgw.HThreadCount,
|
||||
sleepDuration: hwgw.cycleTime - hwgw.hackTime - 1000,
|
||||
stock
|
||||
});
|
||||
await this.scheluder.sleepInWork(250);
|
||||
this.ns.print(`stage 2: executed ${hwgw.HWThreadCount} threads.`);
|
||||
const wpid = this.execute("weaken",{
|
||||
target:this.server.hostname,
|
||||
numThread:hwgw.HWThreadCount,
|
||||
sleepDuration: hwgw.cycleTime - hwgw.weakenTime - 1000,
|
||||
stock
|
||||
});
|
||||
await this.scheluder.sleepInWork(250);
|
||||
this.ns.print(`stage 3: executed ${hwgw.GThreadCount} threads.`);
|
||||
const gpid = this.execute("grow",{
|
||||
target:this.server.hostname,
|
||||
numThread:hwgw.GThreadCount,
|
||||
sleepDuration: hwgw.cycleTime - hwgw.growTime - 1000,
|
||||
stock
|
||||
});
|
||||
await this.scheluder.sleepInWork(250);
|
||||
this.ns.print(`stage 4: executed ${hwgw.GWThreadCount} threads.`);
|
||||
const gwpid = this.execute("weaken",{
|
||||
target:this.server.hostname,
|
||||
numThread:hwgw.GWThreadCount,
|
||||
sleepDuration: hwgw.cycleTime - hwgw.weakenTime - 1000,
|
||||
stock
|
||||
});
|
||||
await this.scheluder.sleepInWork(250);
|
||||
return [...hpid, ...wpid, ...gpid, ...gwpid];
|
||||
}
|
||||
|
||||
calcHWGW(): HackCalculation {
|
||||
const helper = new FormulaHelper(this.ns);
|
||||
const cycleTime = 1 + helper.calculateWeakenTime(this.server);
|
||||
const ramPerSec = Math.floor(this.totalRam / (cycleTime / 1000));
|
||||
const [min,minInfo] = this.getMinThreadCount();
|
||||
const minRam = getTotalRamOf(minInfo);
|
||||
if(minRam > ramPerSec){
|
||||
return minInfo;
|
||||
}
|
||||
// linear search
|
||||
let prev = minInfo;
|
||||
for (let i = min+1; i < min + 100; i++) {
|
||||
const info = this.calcBatchResource(i);
|
||||
if(info === null) break;
|
||||
if(getTotalRamOf(info) > ramPerSec){
|
||||
return prev;
|
||||
}
|
||||
prev = info;
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
getMinThreadCount():[number,HackCalculation]{
|
||||
let minCE = 0;
|
||||
let minHC = 0;
|
||||
let minInfo: HackCalculation;
|
||||
for (let i = 1; i < 100; i++) {
|
||||
const info = this.calcBatchResource(i);
|
||||
if(info === null) break;
|
||||
const ce = info.earnMoneyPerCycle / info.totalThreadCount;
|
||||
if (ce >= minCE) {
|
||||
minCE = ce;
|
||||
minHC = i;
|
||||
minInfo = info;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return [minHC,minInfo!];
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,9 +392,140 @@ export function requestHWGW(req: ReserveRequest, target: string): void {
|
||||
localStorage.setItem(key, JSON.stringify(requests));
|
||||
}
|
||||
|
||||
//export async function batchDaemon(ns: NS): Promise<void> {
|
||||
// const mgr = new HWGWBatchManager(ns, BATCH_KEY);
|
||||
// for (; ;) {
|
||||
// await mgr.tick();
|
||||
// }
|
||||
//}
|
||||
export function popHWGWRequest(hostname: string): ReserveRequest[]{
|
||||
const key = getKeyOfHWGWBatchManager(hostname);
|
||||
const text = localStorage.getItem(key)
|
||||
if(text === null){
|
||||
return [];
|
||||
}
|
||||
localStorage.setItem(key,"[]");
|
||||
return JSON.parse(text) as ReserveRequest[];
|
||||
}
|
||||
|
||||
export async function batchDaemon(ns: NS, hostname: string): Promise<void> {
|
||||
ns.disableLog("getBitNodeMultipliers");
|
||||
ns.disableLog("sleep");
|
||||
const mgr = new HWGWBatchManager(ns, hostname);
|
||||
for (;;) {
|
||||
const requests = popHWGWRequest(hostname);
|
||||
for (const req of requests) {
|
||||
mgr.reserve(req.hostname, req.usableRam);
|
||||
}
|
||||
const hwgw = mgr.calcHWGW();
|
||||
if (hwgw !== null && mgr.getUsableTotalRam() >= getTotalRamOf(hwgw)) {
|
||||
ns.print(`hwgw: total ${hwgw.totalThreadCount} threads.`);
|
||||
mgr.execBatch(hwgw);
|
||||
}
|
||||
for (let i = 0; i < 4; i++) {
|
||||
await mgr.scheluder.tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getKeyOfGrowBatchManager(hostname: string): string{
|
||||
return `Grow-${hostname}`;
|
||||
}
|
||||
export function popGrowRequest(hostname: string): ReserveRequest[]{
|
||||
const key = getKeyOfGrowBatchManager(hostname);
|
||||
const text = localStorage.getItem(key)
|
||||
if(text === null){
|
||||
return [];
|
||||
}
|
||||
localStorage.setItem(key,"[]");
|
||||
return JSON.parse(text) as ReserveRequest[];
|
||||
}
|
||||
export function requestGrow(req: ReserveRequest, target: string): void {
|
||||
const key = getKeyOfGrowBatchManager(target);
|
||||
const data = localStorage.getItem(key);
|
||||
let requests: ReserveRequest[];
|
||||
if (data) {
|
||||
requests = JSON.parse(data);
|
||||
}
|
||||
else {
|
||||
requests = [];
|
||||
}
|
||||
requests.push(req);
|
||||
localStorage.setItem(key, JSON.stringify(requests));
|
||||
}
|
||||
|
||||
|
||||
class GrowManager extends BatchManager {
|
||||
constructor(ns: NS, hostname: string) {
|
||||
super(ns, hostname);
|
||||
}
|
||||
|
||||
async execStraigy(stock: boolean): Promise<void> {
|
||||
const helper = new FormulaHelper(this.ns);
|
||||
const difficultyMargin = 1;
|
||||
if(this.server.hackDifficulty > this.server.minDifficulty + difficultyMargin){
|
||||
const weakenThread = helper.calculateWeakenThreadCountToTargetSecurity(
|
||||
this.server.hackDifficulty, this.server.minDifficulty);
|
||||
const g = this.execute("weaken", {
|
||||
target: this.server.hostname,
|
||||
numThread: weakenThread,
|
||||
sleepDuration: 1,
|
||||
stock
|
||||
});
|
||||
this.ns.print("[PROCESS] weakened");
|
||||
const work = async (): Promise<void> => {
|
||||
await this.execStraigy(stock);
|
||||
}
|
||||
this.scheluder.onPidTerminate(g[0], {
|
||||
work
|
||||
});
|
||||
}
|
||||
|
||||
const moneyFactor = 0.8;
|
||||
if(this.server.moneyAvailable > this.server.moneyMax * moneyFactor){
|
||||
return;
|
||||
}
|
||||
const totalRam = this.getUsableTotalRam();
|
||||
const growThread = Math.floor(totalRam / (getRamOfScript(this.ns, "grow") * 3));
|
||||
const weakenThread = growThread * 2;
|
||||
const growTime = helper.calculateGrowTime(this.server);
|
||||
const weakenTime = helper.calculateWeakenTime(this.server);
|
||||
|
||||
this.execute("weaken", {
|
||||
target: this.server.hostname,
|
||||
numThread: weakenThread,
|
||||
sleepDuration: 0,
|
||||
});
|
||||
await this.scheluder.sleepInWork(250);
|
||||
const g = this.execute("grow", {
|
||||
target: this.server.hostname,
|
||||
numThread: growThread,
|
||||
sleepDuration: weakenTime - growTime,
|
||||
stock
|
||||
});
|
||||
|
||||
const work = async (): Promise<void> => {
|
||||
await this.execStraigy(stock);
|
||||
}
|
||||
this.scheluder.onPidTerminate(g[0], {
|
||||
work
|
||||
});
|
||||
}
|
||||
|
||||
empty(): boolean {
|
||||
return this.scheluder.empty();
|
||||
}
|
||||
}
|
||||
|
||||
export async function growDaemon(ns: NS, hostname: string): Promise<void> {
|
||||
ns.disableLog("getBitNodeMultipliers");
|
||||
ns.disableLog("sleep");
|
||||
const mgr = new GrowManager(ns, hostname);
|
||||
processRequest();
|
||||
mgr.execStraigy(false);
|
||||
while (!mgr.empty()) {
|
||||
processRequest()
|
||||
await mgr.scheluder.tick();
|
||||
}
|
||||
|
||||
function processRequest(): void{
|
||||
const requests = popGrowRequest(hostname);
|
||||
for (const req of requests) {
|
||||
mgr.reserve(req.hostname, req.usableRam);
|
||||
}
|
||||
}
|
||||
}
|
536
src/lib/colors.ts
Normal file
536
src/lib/colors.ts
Normal file
@ -0,0 +1,536 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// A module to print ANSI terminal colors. Inspired by chalk, kleur, and colors
|
||||
// on npm.
|
||||
|
||||
/**
|
||||
* String formatters and utilities for dealing with ANSI color codes.
|
||||
*
|
||||
* This module is browser compatible.
|
||||
*
|
||||
* ```ts
|
||||
* import { bgBlue, red, bold } from "https://deno.land/std@$STD_VERSION/fmt/colors.ts";
|
||||
* console.log(bgBlue(red(bold("Hello world!"))));
|
||||
* ```
|
||||
*
|
||||
* This module supports `NO_COLOR` environmental variable disabling any coloring
|
||||
* if `NO_COLOR` is set.
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
|
||||
const noColor = false;
|
||||
|
||||
interface Code {
|
||||
open: string;
|
||||
close: string;
|
||||
regexp: RegExp;
|
||||
}
|
||||
|
||||
/** RGB 8-bits per channel. Each in range `0->255` or `0x00->0xff` */
|
||||
interface Rgb {
|
||||
r: number;
|
||||
g: number;
|
||||
b: number;
|
||||
}
|
||||
|
||||
let enabled = !noColor;
|
||||
|
||||
/**
|
||||
* Set changing text color to enabled or disabled
|
||||
* @param value
|
||||
*/
|
||||
export function setColorEnabled(value: boolean) {
|
||||
if (noColor) {
|
||||
return;
|
||||
}
|
||||
|
||||
enabled = value;
|
||||
}
|
||||
|
||||
/** Get whether text color change is enabled or disabled. */
|
||||
export function getColorEnabled(): boolean {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds color code
|
||||
* @param open
|
||||
* @param close
|
||||
*/
|
||||
function code(open: number[], close: number): Code {
|
||||
return {
|
||||
open: `\x1b[${open.join(";")}m`,
|
||||
close: `\x1b[${close}m`,
|
||||
regexp: new RegExp(`\\x1b\\[${close}m`, "g"),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies color and background based on color code and its associated text
|
||||
* @param str text to apply color settings to
|
||||
* @param code color code to apply
|
||||
*/
|
||||
function run(str: string, code: Code): string {
|
||||
return enabled
|
||||
? `${code.open}${str.replace(code.regexp, code.open)}${code.close}`
|
||||
: str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the text modified
|
||||
* @param str text to reset
|
||||
*/
|
||||
export function reset(str: string): string {
|
||||
return run(str, code([0], 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the text bold.
|
||||
* @param str text to make bold
|
||||
*/
|
||||
export function bold(str: string): string {
|
||||
return run(str, code([1], 22));
|
||||
}
|
||||
|
||||
/**
|
||||
* The text emits only a small amount of light.
|
||||
* @param str text to dim
|
||||
*/
|
||||
export function dim(str: string): string {
|
||||
return run(str, code([2], 22));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the text italic.
|
||||
* @param str text to make italic
|
||||
*/
|
||||
export function italic(str: string): string {
|
||||
return run(str, code([3], 23));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the text underline.
|
||||
* @param str text to underline
|
||||
*/
|
||||
export function underline(str: string): string {
|
||||
return run(str, code([4], 24));
|
||||
}
|
||||
|
||||
/**
|
||||
* Invert background color and text color.
|
||||
* @param str text to invert its color
|
||||
*/
|
||||
export function inverse(str: string): string {
|
||||
return run(str, code([7], 27));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the text hidden.
|
||||
* @param str text to hide
|
||||
*/
|
||||
export function hidden(str: string): string {
|
||||
return run(str, code([8], 28));
|
||||
}
|
||||
|
||||
/**
|
||||
* Put horizontal line through the center of the text.
|
||||
* @param str text to strike through
|
||||
*/
|
||||
export function strikethrough(str: string): string {
|
||||
return run(str, code([9], 29));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to black.
|
||||
* @param str text to make black
|
||||
*/
|
||||
export function black(str: string): string {
|
||||
return run(str, code([30], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to red.
|
||||
* @param str text to make red
|
||||
*/
|
||||
export function red(str: string): string {
|
||||
return run(str, code([31], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to green.
|
||||
* @param str text to make green
|
||||
*/
|
||||
export function green(str: string): string {
|
||||
return run(str, code([32], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to yellow.
|
||||
* @param str text to make yellow
|
||||
*/
|
||||
export function yellow(str: string): string {
|
||||
return run(str, code([33], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to blue.
|
||||
* @param str text to make blue
|
||||
*/
|
||||
export function blue(str: string): string {
|
||||
return run(str, code([34], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to magenta.
|
||||
* @param str text to make magenta
|
||||
*/
|
||||
export function magenta(str: string): string {
|
||||
return run(str, code([35], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to cyan.
|
||||
* @param str text to make cyan
|
||||
*/
|
||||
export function cyan(str: string): string {
|
||||
return run(str, code([36], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to white.
|
||||
* @param str text to make white
|
||||
*/
|
||||
export function white(str: string): string {
|
||||
return run(str, code([37], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to gray.
|
||||
* @param str text to make gray
|
||||
*/
|
||||
export function gray(str: string): string {
|
||||
return brightBlack(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to bright black.
|
||||
* @param str text to make bright-black
|
||||
*/
|
||||
export function brightBlack(str: string): string {
|
||||
return run(str, code([90], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to bright red.
|
||||
* @param str text to make bright-red
|
||||
*/
|
||||
export function brightRed(str: string): string {
|
||||
return run(str, code([91], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to bright green.
|
||||
* @param str text to make bright-green
|
||||
*/
|
||||
export function brightGreen(str: string): string {
|
||||
return run(str, code([92], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to bright yellow.
|
||||
* @param str text to make bright-yellow
|
||||
*/
|
||||
export function brightYellow(str: string): string {
|
||||
return run(str, code([93], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to bright blue.
|
||||
* @param str text to make bright-blue
|
||||
*/
|
||||
export function brightBlue(str: string): string {
|
||||
return run(str, code([94], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to bright magenta.
|
||||
* @param str text to make bright-magenta
|
||||
*/
|
||||
export function brightMagenta(str: string): string {
|
||||
return run(str, code([95], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to bright cyan.
|
||||
* @param str text to make bright-cyan
|
||||
*/
|
||||
export function brightCyan(str: string): string {
|
||||
return run(str, code([96], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color to bright white.
|
||||
* @param str text to make bright-white
|
||||
*/
|
||||
export function brightWhite(str: string): string {
|
||||
return run(str, code([97], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to black.
|
||||
* @param str text to make its background black
|
||||
*/
|
||||
export function bgBlack(str: string): string {
|
||||
return run(str, code([40], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to red.
|
||||
* @param str text to make its background red
|
||||
*/
|
||||
export function bgRed(str: string): string {
|
||||
return run(str, code([41], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to green.
|
||||
* @param str text to make its background green
|
||||
*/
|
||||
export function bgGreen(str: string): string {
|
||||
return run(str, code([42], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to yellow.
|
||||
* @param str text to make its background yellow
|
||||
*/
|
||||
export function bgYellow(str: string): string {
|
||||
return run(str, code([43], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to blue.
|
||||
* @param str text to make its background blue
|
||||
*/
|
||||
export function bgBlue(str: string): string {
|
||||
return run(str, code([44], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to magenta.
|
||||
* @param str text to make its background magenta
|
||||
*/
|
||||
export function bgMagenta(str: string): string {
|
||||
return run(str, code([45], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to cyan.
|
||||
* @param str text to make its background cyan
|
||||
*/
|
||||
export function bgCyan(str: string): string {
|
||||
return run(str, code([46], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to white.
|
||||
* @param str text to make its background white
|
||||
*/
|
||||
export function bgWhite(str: string): string {
|
||||
return run(str, code([47], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to bright black.
|
||||
* @param str text to make its background bright-black
|
||||
*/
|
||||
export function bgBrightBlack(str: string): string {
|
||||
return run(str, code([100], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to bright red.
|
||||
* @param str text to make its background bright-red
|
||||
*/
|
||||
export function bgBrightRed(str: string): string {
|
||||
return run(str, code([101], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to bright green.
|
||||
* @param str text to make its background bright-green
|
||||
*/
|
||||
export function bgBrightGreen(str: string): string {
|
||||
return run(str, code([102], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to bright yellow.
|
||||
* @param str text to make its background bright-yellow
|
||||
*/
|
||||
export function bgBrightYellow(str: string): string {
|
||||
return run(str, code([103], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to bright blue.
|
||||
* @param str text to make its background bright-blue
|
||||
*/
|
||||
export function bgBrightBlue(str: string): string {
|
||||
return run(str, code([104], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to bright magenta.
|
||||
* @param str text to make its background bright-magenta
|
||||
*/
|
||||
export function bgBrightMagenta(str: string): string {
|
||||
return run(str, code([105], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to bright cyan.
|
||||
* @param str text to make its background bright-cyan
|
||||
*/
|
||||
export function bgBrightCyan(str: string): string {
|
||||
return run(str, code([106], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color to bright white.
|
||||
* @param str text to make its background bright-white
|
||||
*/
|
||||
export function bgBrightWhite(str: string): string {
|
||||
return run(str, code([107], 49));
|
||||
}
|
||||
|
||||
/* Special Color Sequences */
|
||||
|
||||
/**
|
||||
* Clam and truncate color codes
|
||||
* @param n
|
||||
* @param max number to truncate to
|
||||
* @param min number to truncate from
|
||||
*/
|
||||
function clampAndTruncate(n: number, max = 255, min = 0): number {
|
||||
return Math.trunc(Math.max(Math.min(n, max), min));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color using paletted 8bit colors.
|
||||
* https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
|
||||
* @param str text color to apply paletted 8bit colors to
|
||||
* @param color code
|
||||
*/
|
||||
export function rgb8(str: string, color: number): string {
|
||||
return run(str, code([38, 5, clampAndTruncate(color)], 39));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color using paletted 8bit colors.
|
||||
* https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
|
||||
* @param str text color to apply paletted 8bit background colors to
|
||||
* @param color code
|
||||
*/
|
||||
export function bgRgb8(str: string, color: number): string {
|
||||
return run(str, code([48, 5, clampAndTruncate(color)], 49));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text color using 24bit rgb.
|
||||
* `color` can be a number in range `0x000000` to `0xffffff` or
|
||||
* an `Rgb`.
|
||||
*
|
||||
* To produce the color magenta:
|
||||
*
|
||||
* ```ts
|
||||
* import { rgb24 } from "./colors.ts";
|
||||
* rgb24("foo", 0xff00ff);
|
||||
* rgb24("foo", {r: 255, g: 0, b: 255});
|
||||
* ```
|
||||
* @param str text color to apply 24bit rgb to
|
||||
* @param color code
|
||||
*/
|
||||
export function rgb24(str: string, color: number | Rgb): string {
|
||||
if (typeof color === "number") {
|
||||
return run(
|
||||
str,
|
||||
code(
|
||||
[38, 2, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff],
|
||||
39,
|
||||
),
|
||||
);
|
||||
}
|
||||
return run(
|
||||
str,
|
||||
code(
|
||||
[
|
||||
38,
|
||||
2,
|
||||
clampAndTruncate(color.r),
|
||||
clampAndTruncate(color.g),
|
||||
clampAndTruncate(color.b),
|
||||
],
|
||||
39,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set background color using 24bit rgb.
|
||||
* `color` can be a number in range `0x000000` to `0xffffff` or
|
||||
* an `Rgb`.
|
||||
*
|
||||
* To produce the color magenta:
|
||||
*
|
||||
* ```ts
|
||||
* import { bgRgb24 } from "./colors.ts";
|
||||
* bgRgb24("foo", 0xff00ff);
|
||||
* bgRgb24("foo", {r: 255, g: 0, b: 255});
|
||||
* ```
|
||||
* @param str text color to apply 24bit rgb to
|
||||
* @param color code
|
||||
*/
|
||||
export function bgRgb24(str: string, color: number | Rgb): string {
|
||||
if (typeof color === "number") {
|
||||
return run(
|
||||
str,
|
||||
code(
|
||||
[48, 2, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff],
|
||||
49,
|
||||
),
|
||||
);
|
||||
}
|
||||
return run(
|
||||
str,
|
||||
code(
|
||||
[
|
||||
48,
|
||||
2,
|
||||
clampAndTruncate(color.r),
|
||||
clampAndTruncate(color.g),
|
||||
clampAndTruncate(color.b),
|
||||
],
|
||||
49,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// https://github.com/chalk/ansi-regex/blob/02fa893d619d3da85411acc8fd4e2eea0e95a9d9/index.js
|
||||
const ANSI_PATTERN = new RegExp(
|
||||
[
|
||||
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
|
||||
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))",
|
||||
].join("|"),
|
||||
"g",
|
||||
);
|
||||
|
||||
/**
|
||||
* Remove ANSI escape codes from the string.
|
||||
* @param string to remove ANSI escape codes from
|
||||
*/
|
||||
export function stripColor(string: string): string {
|
||||
return string.replace(ANSI_PATTERN, "");
|
||||
}
|
@ -14,6 +14,7 @@ import {selectAllServerList} from "lib/servers";
|
||||
import { logFile } from "./log";
|
||||
import { SolveFailError } from "./solve/unsolved";
|
||||
import { RLECompressionSolve, decompressLZSolve, compressLZSolve } from "./solve/compression";
|
||||
import {caesarCipherSolve} from "./solve/caesarCipher";
|
||||
|
||||
export { SolveFailError } from "./solve/unsolved";
|
||||
|
||||
@ -152,13 +153,11 @@ const ContractMAP: {[key:string]:ContractSolver} = {
|
||||
"Compression III: LZ Compression": {
|
||||
name: "Compression III: LZ Compression",
|
||||
solve: compressLZSolve,
|
||||
},/*
|
||||
},
|
||||
"Encryption I: Caesar Cipher": {
|
||||
name: "Encryption I: Caesar Cipher",
|
||||
solve() {
|
||||
notImplemented();
|
||||
}
|
||||
},
|
||||
solve: caesarCipherSolve,
|
||||
},/*
|
||||
"Encryption II: Vigenère Cipher": {
|
||||
name: "Encryption II: Vigenère Cipher",
|
||||
solve() {
|
||||
|
@ -206,6 +206,11 @@ export function canBeAccessBitNode(ns: NS): boolean {
|
||||
}
|
||||
|
||||
export function getBitNodeMultipliersSafe(ns: NS): BitNodeMultipliers {
|
||||
const fnName = "getBitNodeMultipliers";
|
||||
const isEnabled = ns.isLogEnabled(fnName);
|
||||
ns.disableLog("disableLog");
|
||||
ns.disableLog("enableLog");
|
||||
ns.disableLog("getBitNodeMultipliers");
|
||||
try {
|
||||
return ns.getBitNodeMultipliers();
|
||||
} catch (error) {
|
||||
@ -213,6 +218,10 @@ export function getBitNodeMultipliersSafe(ns: NS): BitNodeMultipliers {
|
||||
return DefaultBitNodeMultipliers;
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
if (isEnabled) {
|
||||
ns.enableLog("getBitNodeMultipliers");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,7 +231,10 @@ export class FormulaHelper {
|
||||
this.ns = ns;
|
||||
}
|
||||
calculateWeakenThreadCountToTargetSecurity(targetSecurity: number, curSecurity: number, cores = 1): number {
|
||||
const k = targetSecurity - targetSecurity;
|
||||
if(curSecurity < targetSecurity) {
|
||||
return 0;
|
||||
}
|
||||
const k = curSecurity - targetSecurity;
|
||||
const c = this.ns.weakenAnalyze(1, cores);
|
||||
return k / c;
|
||||
}
|
||||
@ -241,21 +253,31 @@ export class FormulaHelper {
|
||||
return ServerWeakenAmount * nThread * coreBonus * mul.ServerWeakenRate;
|
||||
}
|
||||
/**
|
||||
* 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
|
||||
* @param server
|
||||
* @returns seconds to complete a weaken operation
|
||||
* @returns milliseconds to complete a weaken operation
|
||||
*/
|
||||
calculateWeakenTime(server: Server): number {
|
||||
const player = this.ns.getPlayer();
|
||||
return calculateWeakenTime(server, player);
|
||||
return calculateWeakenTime(server, player) * 1000;
|
||||
}
|
||||
/**
|
||||
* Returns time it takes to complete a grow operation on a server, in milliseconds
|
||||
* @param server
|
||||
* @returns milliseconds to complete a grow operation
|
||||
*/
|
||||
calculateGrowTime(server: Server): number {
|
||||
const player = this.ns.getPlayer();
|
||||
return calculateGrowTime(server, player);
|
||||
return calculateGrowTime(server, player) * 1000;
|
||||
}
|
||||
/**
|
||||
* Returns time it takes to complete a hacking operation on a server, in milliseconds
|
||||
* @param server
|
||||
* @returns milliseconds to complete a hacking operation
|
||||
*/
|
||||
calculateHackingTime(server: Server): number {
|
||||
const player = this.ns.getPlayer();
|
||||
return calculateHackingTime(server, player);
|
||||
return calculateHackingTime(server, player) * 1000;
|
||||
}
|
||||
/**
|
||||
* Hack
|
||||
|
@ -2,7 +2,8 @@ import {NS} from "@ns"
|
||||
|
||||
export async function logFile(ns:NS,logFilename:string, data: unknown):Promise<void>{
|
||||
logFilename = logFilename.replaceAll(" ","-");
|
||||
logFilename = `/log/${logFilename}${Date.now()}.txt`;
|
||||
logFilename = logFilename.replaceAll(":","-");
|
||||
logFilename = `/log/${logFilename}.txt`;
|
||||
const loggedData = JSON.stringify(data);
|
||||
if(ns.fileExists(logFilename)){
|
||||
await ns.write(logFilename,"\n"+loggedData,"a");
|
||||
|
@ -1,38 +1,185 @@
|
||||
import {NS } from "@ns";
|
||||
import {NS} from "@ns";
|
||||
|
||||
|
||||
type WorkFunc = ()=>void;
|
||||
type WorkChunk = {
|
||||
onStart: WorkFunc[];
|
||||
onFinish: WorkFunc[];
|
||||
}
|
||||
|
||||
interface Tickable {
|
||||
/**
|
||||
* tick in scheduler
|
||||
*/
|
||||
export interface Tickable {
|
||||
/**
|
||||
* tick in scheduler
|
||||
*/
|
||||
tick(): void;
|
||||
/**
|
||||
* no work to run in this tick.
|
||||
*/
|
||||
empty(): boolean;
|
||||
}
|
||||
|
||||
class PidTerminateExecutor{
|
||||
/**
|
||||
* worker in scheduler
|
||||
*/
|
||||
export interface Work {
|
||||
work: (() => Promise<void>) | (()=>void);
|
||||
}
|
||||
|
||||
/**
|
||||
* set of work to be executed at the same time
|
||||
*/
|
||||
export class WorkSet implements Work{
|
||||
works: Work[];
|
||||
constructor(){
|
||||
this.works = [];
|
||||
}
|
||||
add(work: Work): void{
|
||||
this.works.push(work);
|
||||
}
|
||||
remove(work: Work): void{
|
||||
this.works = this.works.filter(x=>x !== work);
|
||||
}
|
||||
concat(other: WorkSet): void{
|
||||
this.works = this.works.concat(other.works);
|
||||
}
|
||||
async work(): Promise<void>{
|
||||
for(const work of this.works){
|
||||
await work.work();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function mergeWork(...args: Work[]): WorkSet{
|
||||
const workSet = new WorkSet();
|
||||
for(const work of args){
|
||||
if(work instanceof WorkSet){
|
||||
workSet.concat(work);
|
||||
}
|
||||
else {
|
||||
workSet.add(work);
|
||||
}
|
||||
}
|
||||
return workSet;
|
||||
}
|
||||
|
||||
class PidTerminateExecutor implements Tickable{
|
||||
ns: NS;
|
||||
lastCheck: number;
|
||||
pidSet: Map<number, EventTarget>;
|
||||
tick(): void{
|
||||
const current = this.ns.getTimeSinceLastAug();
|
||||
const deadScripts = this.ns.getRecentScripts().filter(x=>x.timeOfDeath >= current);
|
||||
deadScripts.forEach(x=>{
|
||||
if(this.pidSet.has(x.pid)){
|
||||
const target = this.pidSet.get(x.pid);
|
||||
target?.dispatchEvent(new )
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
pidSet: Map<number, Work>;
|
||||
|
||||
class TimerExecutor{
|
||||
ns: NS;
|
||||
constructor(ns: NS){
|
||||
this.ns = ns;
|
||||
this.lastCheck = Date.now();
|
||||
this.pidSet = new Map();
|
||||
}
|
||||
watchPid(pid: number, work: Work): void{
|
||||
if(this.pidSet.has(pid)){
|
||||
throw new Error(`pid ${pid} is already watched`);
|
||||
}
|
||||
this.pidSet.set(pid, work);
|
||||
}
|
||||
asdf():{
|
||||
|
||||
empty(): boolean{
|
||||
return this.pidSet.size === 0;
|
||||
}
|
||||
|
||||
async tick(): Promise<void>{
|
||||
const current = Date.now();
|
||||
const deadScripts = this.ns.getRecentScripts().filter(x=>x.timeOfDeath.getTime() >= this.lastCheck);
|
||||
for(const script of deadScripts){
|
||||
const target = this.pidSet.get(script.pid);
|
||||
if(target){
|
||||
await target.work();
|
||||
}
|
||||
this.pidSet.delete(script.pid);
|
||||
}
|
||||
this.lastCheck = current;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeTime(time: number, timeResolution: number): number{
|
||||
return Math.floor(time / timeResolution) * timeResolution;
|
||||
}
|
||||
|
||||
class TimerExecutor implements Tickable{
|
||||
ns: NS;
|
||||
timerResolution: number;
|
||||
timerStart: number;
|
||||
workBucket: Map<number, WorkSet>;
|
||||
constructor(ns: NS, timerResolution = 250){
|
||||
this.ns = ns;
|
||||
this.workBucket = new Map;
|
||||
this.timerResolution = timerResolution;
|
||||
this.timerStart = performance.now();
|
||||
}
|
||||
|
||||
empty(): boolean{
|
||||
return this.workBucket.size === 0;
|
||||
}
|
||||
|
||||
setTimeout(work: Work, delay: number): void {
|
||||
const time = performance.now() + delay - this.timerStart;
|
||||
const normalizedTime = normalizeTime(time, this.timerResolution);
|
||||
const workSet = this.workBucket.get(normalizedTime);
|
||||
if(workSet){
|
||||
workSet.add(work);
|
||||
}
|
||||
else{
|
||||
this.workBucket.set(normalizedTime, mergeWork(work));
|
||||
}
|
||||
}
|
||||
async tick(): Promise<void> {
|
||||
const current = performance.now();
|
||||
const normalizedCurrent = normalizeTime(current-this.timerStart, this.timerResolution);
|
||||
const workSet = this.workBucket.get(normalizedCurrent);
|
||||
if(workSet){
|
||||
await workSet.work();
|
||||
this.workBucket.delete(normalizedCurrent);
|
||||
}
|
||||
}
|
||||
async sleepForTick(): Promise<void>{
|
||||
const current = performance.now();
|
||||
|
||||
const normalizedCurrent = normalizeTime(current-this.timerStart, this.timerResolution);
|
||||
const next = normalizedCurrent + this.timerResolution;
|
||||
|
||||
const nextTime = this.timerStart + next;
|
||||
const sleepTime = nextTime - current;
|
||||
//this.ns.print(`Sleeping for ${sleepTime}ms`);
|
||||
await this.ns.sleep(sleepTime);
|
||||
}
|
||||
}
|
||||
|
||||
export class Scheduler{
|
||||
ns: NS;
|
||||
timeResolution: number;
|
||||
pidWatcher: PidTerminateExecutor;
|
||||
timerWatcher: TimerExecutor;
|
||||
constructor(ns: NS, timeResolution = 250){
|
||||
this.ns = ns;
|
||||
this.timeResolution = timeResolution;
|
||||
this.pidWatcher = new PidTerminateExecutor(ns);
|
||||
this.timerWatcher = new TimerExecutor(ns, timeResolution);
|
||||
}
|
||||
|
||||
empty(): boolean{
|
||||
return this.pidWatcher.empty() && this.timerWatcher.empty();
|
||||
}
|
||||
|
||||
setTimeout(work: Work, delay: number): void {
|
||||
this.timerWatcher.setTimeout(work, delay);
|
||||
}
|
||||
|
||||
sleepInWork(delay: number): Promise<void>{
|
||||
return new Promise<void>(resolve=>{
|
||||
this.setTimeout({work(){
|
||||
resolve();
|
||||
} }, delay);
|
||||
});
|
||||
}
|
||||
onPidTerminate(pid: number, work: Work): void{
|
||||
this.pidWatcher.watchPid(pid, work);
|
||||
}
|
||||
|
||||
async tick(): Promise<void>{
|
||||
await this.pidWatcher.tick();
|
||||
await this.timerWatcher.tick();
|
||||
await this.timerWatcher.sleepForTick();
|
||||
}
|
||||
}
|
@ -7,12 +7,15 @@ export function arrayJump2(arr:number[]): number{
|
||||
d[j] = Math.min(d[j],d[i]+1);
|
||||
}
|
||||
}
|
||||
console.log(d);
|
||||
return d[arr.length - 1];
|
||||
}
|
||||
|
||||
export function arrayJump2Solve(arr:number[]): number{
|
||||
return arrayJump2(arr);
|
||||
const v = arrayJump2(arr);
|
||||
if (v === Infinity) {
|
||||
return 0;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
export const testcases: Array<[number[],number]> = [
|
||||
|
30
src/lib/solve/caesarCipher.ts
Normal file
30
src/lib/solve/caesarCipher.ts
Normal file
@ -0,0 +1,30 @@
|
||||
const alphabet = 'abcdefghijklmnopqrstuvwxyz'.toUpperCase();
|
||||
|
||||
export function caesarCipher(str: string, key: number): string {
|
||||
return str.split('').map((ch) => {
|
||||
if (ch === ' ') return ch;
|
||||
const idx = alphabet.indexOf(ch);
|
||||
return alphabet[(idx + key) % alphabet.length];
|
||||
}).join('');
|
||||
}
|
||||
|
||||
type CaesarCipherInput = [string, number];
|
||||
|
||||
export function caesarCipherSolve([plain, key]: CaesarCipherInput): string[] {
|
||||
return [caesarCipher(plain, 26-key)];
|
||||
}
|
||||
|
||||
//type TestCase = [CaesarCipherInput, string];
|
||||
//
|
||||
//const TestCases: TestCase[] = [
|
||||
// [["ABC", -1], "BCD"],
|
||||
// [["ABC", -2], "CDE"],
|
||||
// [["ABC", -3], "DEF"],
|
||||
// [["ABC", -4], "EFG"],
|
||||
// [["ABC", -5], "FGH"],
|
||||
// [["ABC", -6], "GHI"],
|
||||
// [["HELLO WORLD", -1], "IFMMP XPSME"],
|
||||
// [["Z", 1], "A"],
|
||||
// [["MODEM FRAME VIRUS TRASH POPUP", -13], "ZBQRZ SENZR IVEHF GENFU CBCHC"]
|
||||
// [["LOGIN MOUSE TABLE PRINT FLASH", -18], "TWOQV UWCAM BIJTM XZQVB NTIAP"]
|
||||
//]
|
@ -50,7 +50,11 @@ export function graph2coloring([nVertex,edges]:Input):number[]{
|
||||
}
|
||||
}
|
||||
export function graph2coloringSolve(input:Input):string[]{
|
||||
return graph2coloring(input).map(x=>x.toString());
|
||||
const ret = graph2coloring(input).map(x=>x.toString());
|
||||
if (ret.length === 0) {
|
||||
return ["[]"];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
export type TestCase = [
|
||||
Input,
|
||||
|
20
src/rainbow.ts
Normal file
20
src/rainbow.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { NS } from '@ns'
|
||||
import { parse } from './lib/flag';
|
||||
import { sprintf } from './lib/printf';
|
||||
|
||||
function guess(ns:NS,text:string):void{
|
||||
// undocumented function
|
||||
// @ts-ignore TS2339
|
||||
return ns.rainbow(text);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
export async function main(ns: NS) : Promise<void> {
|
||||
const flag = parse(ns.args.map(x=>x.toString()));
|
||||
if(flag.h || flag.help){
|
||||
const msg = ['run cmd']
|
||||
msg.forEach(x=>ns.tprint(x));
|
||||
return;
|
||||
}
|
||||
guess(ns,"noodles")
|
||||
}
|
30
src/runtest.ts
Normal file
30
src/runtest.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { NS } from '@ns'
|
||||
import { parse } from './lib/flag';
|
||||
import { red, rgb24, blue, bgBrightMagenta } from './lib/colors';
|
||||
|
||||
|
||||
// eslint-disable-next-line require-await
|
||||
export async function main(ns: NS) : Promise<void> {
|
||||
const flag = parse(ns.args.map(x=>x.toString()));
|
||||
if(flag.h || flag.help){
|
||||
const msg = ['run cmd']
|
||||
msg.forEach(x=>ns.tprint(x));
|
||||
return;
|
||||
}
|
||||
ns.tprint(red("hello world red "));
|
||||
ns.tprint(blue("hello world blue"));
|
||||
ns.tprint(bgBrightMagenta("hello world bgBrightMagenta"));
|
||||
ns.tprint(rgb24("hello world #00ff00", 0x00ff00));
|
||||
ns.tprint(rgb24("hello world #f0f000", 0xf0f000));
|
||||
ns.tprint(rgb24("hello world #0000ff", 0x0000ff));
|
||||
ns.tprint(rgb24("hello world #0000ff", {r:0,g:0,b:255}));
|
||||
//const d = "document"
|
||||
//const doc = eval(d) as Document;
|
||||
//const div = doc.querySelector(".css-1hamw82") as HTMLDivElement;
|
||||
//if(!div){
|
||||
// ns.tprint("div not found");
|
||||
// return;
|
||||
//}
|
||||
//const text = div.innerText;
|
||||
//ns.tprint(text);
|
||||
}
|
Loading…
Reference in New Issue
Block a user