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;
|
return;
|
||||||
}
|
}
|
||||||
const v = parseInt(flag._[0].toString());
|
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 hostname = flag.host ?? flag.t;
|
||||||
const server = ns.getServer(hostname)
|
const server = ns.getServer(hostname)
|
||||||
if(flag.graph){
|
if(flag.graph){
|
||||||
const col = [];
|
const col = [];
|
||||||
for (let i = 1; i < v; i++) {
|
for (let i = 1; i < v; i++) {
|
||||||
const info = calculateBatchResource(ns,hostname,i,server.moneyMax,1);
|
const info = calculateBatchResource(ns,hostname,i,server.moneyMax,1);
|
||||||
|
if(info === null) break;
|
||||||
col.push({
|
col.push({
|
||||||
costEffect :(info.earnMoneyPerSec / info.totalThreadCount),
|
costEffect :(info.earnMoneyPerCycle / info.totalThreadCount),
|
||||||
index: i,
|
index: i,
|
||||||
total: info.totalThreadCount
|
total: info.totalThreadCount
|
||||||
})
|
})
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import { NS, AutocompleteData } from '@ns'
|
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';
|
import { parse } from './lib/flag';
|
||||||
|
|
||||||
|
|
||||||
function help(ns:NS):void{
|
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
|
// eslint-disable-next-line require-await
|
||||||
export async function main(ns : NS) : Promise<void> {
|
export async function main(ns : NS) : Promise<void> {
|
||||||
|
|
||||||
const flag = parse(ns.args.map(String))
|
const flag = parse(ns.args.map(String))
|
||||||
|
|
||||||
const hostname: string|undefined = flag.hostname ?? flag.n;
|
const hostname: string|undefined = flag.hostname ?? flag.n;
|
||||||
@ -22,15 +24,20 @@ export async function main(ns : NS) : Promise<void> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const target = flag._[0].toString();
|
const target = flag._[0].toString();
|
||||||
|
ns.print("check batch file pack ...")
|
||||||
if(!isBatchFilePackInstalled(ns)){
|
if(!isBatchFilePackInstalled(ns)){
|
||||||
await installBatchFilePack(ns);
|
await installBatchFilePack(ns);
|
||||||
}
|
}
|
||||||
|
const server = ns.getServer(hostname)
|
||||||
await scpBatchFilePack(ns,hostname);
|
await scpBatchFilePack(ns,hostname);
|
||||||
|
ns.print("request hwgw ...")
|
||||||
const server = ns.getServer(target);
|
requestHWGW({
|
||||||
ns.tprint();
|
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
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
@ -21,7 +21,7 @@ export async function main(ns: NS): Promise<void> {
|
|||||||
nThread = th;
|
nThread = th;
|
||||||
}
|
}
|
||||||
else {
|
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);
|
const pid = ns.exec("share-server.js",hostname, nThread);
|
||||||
ns.tprint(pid," Process started.");
|
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);
|
const account = new Account(budget);
|
||||||
ns.tail();
|
ns.tail();
|
||||||
const period = 1000;
|
const period = 100;
|
||||||
for (let i = 0; i < iter; i++) {
|
for (let i = 0; i < iter; i++) {
|
||||||
//ns.clearLog()
|
//ns.clearLog()
|
||||||
cycle(ns, account);
|
cycle(ns, account);
|
||||||
await ns.sleep(period);
|
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 { NS, Server } from "@ns"
|
||||||
|
import { info } from "console";
|
||||||
import { calculateServerGrowth, FormulaHelper } from "./formula";
|
import { calculateServerGrowth, FormulaHelper } from "./formula";
|
||||||
|
import { Scheduler } from "./scheduler";
|
||||||
|
|
||||||
export type BatchType = "hack" | "grow" | "weaken" | "weakenLoop";
|
export type BatchType = "hack" | "grow" | "weaken" | "weakenLoop";
|
||||||
|
|
||||||
@ -104,6 +105,7 @@ export interface ExecOption {
|
|||||||
*/
|
*/
|
||||||
numThread?: number;
|
numThread?: number;
|
||||||
/**
|
/**
|
||||||
|
* milliseconds to sleep before exec
|
||||||
* @default 0
|
* @default 0
|
||||||
*/
|
*/
|
||||||
sleepDuration?: number;
|
sleepDuration?: number;
|
||||||
@ -115,8 +117,9 @@ export interface ExecOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function execBatchfile(ns: NS, path: string, option: ExecOption): number {
|
function execBatchfile(ns: NS, path: string, option: ExecOption): number {
|
||||||
|
const uuid = crypto.randomUUID();
|
||||||
return ns.exec(path, option.hostname, option.numThread,
|
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 {
|
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 {
|
export function execWeakenLoop(ns: NS, option: ExecOption): number {
|
||||||
return execBatchfile(ns, "/tmp/weakenLoop.js", option);
|
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{
|
export function getRamOfScript(ns: NS, type: BatchType): number{
|
||||||
return batchFilePack.filter(x=>x.type == type)[0].ram;
|
return batchFilePack.filter(x=>x.type == type)[0].ram;
|
||||||
}
|
}
|
||||||
|
|
||||||
//type BatchType = "hack" | "grow" | "weaken";
|
|
||||||
//
|
|
||||||
//type Batch = {
|
|
||||||
// type: BatchType;
|
|
||||||
// options: ExecOption;
|
|
||||||
//}
|
|
||||||
type ReserveRequest = {
|
type ReserveRequest = {
|
||||||
hostname: string;
|
hostname: string;
|
||||||
usableRam: number;
|
usableRam: number;
|
||||||
@ -156,83 +156,30 @@ interface HWGW {
|
|||||||
GWThreadCount: number;
|
GWThreadCount: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
type WorkReserved = {
|
function getTotalRamOf(hwgw: HWGW): number{
|
||||||
allocated:false;
|
return hwgw.HThreadCount * 1.7 + hwgw.HWThreadCount * 1.75 + hwgw.GThreadCount * 1.75 + hwgw.GWThreadCount * 1.75;
|
||||||
} | {
|
}
|
||||||
allocated:true;
|
|
||||||
hwgw: HWGW;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Resource = {
|
type Resource = {
|
||||||
hostname: string;
|
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 {
|
interface HackCalculation extends HWGW {
|
||||||
earnMoneyPerSec: number;
|
earnMoneyPerCycle: number;
|
||||||
earnExpPerSec: number;
|
earnExpPerCycle: number;
|
||||||
/**
|
/**
|
||||||
* cycle time in seconds.
|
* cycle time in milliseconds.
|
||||||
*/
|
*/
|
||||||
cycleTime: number;
|
cycleTime: number;
|
||||||
totalThreadCount: 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 helper = new FormulaHelper(ns);
|
||||||
const server = ns.getServer(hostname);
|
const server = ns.getServer(hostname);
|
||||||
startMoney ??= server.moneyMax;
|
startMoney ??= server.moneyMax;
|
||||||
@ -242,13 +189,14 @@ export function calculateBatchResource(ns: NS, hostname: string, hackThread: num
|
|||||||
const hackingChance = helper.calculateHackingChance(server);
|
const hackingChance = helper.calculateHackingChance(server);
|
||||||
const earnMoneyPerCycle = hackThread * percentMoneyHacked * startMoney * hackingChance;
|
const earnMoneyPerCycle = hackThread * percentMoneyHacked * startMoney * hackingChance;
|
||||||
const earnExpPerCycle = helper.calculateHackingExpGain(server) * hackThread * 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 increasedSecurityAfterHack = helper.calculateHackSecurity(hackThread) + server.minDifficulty;
|
||||||
const nWeakenHackThreads = Math.ceil(helper.calculateWeakenThreadCountToTargetSecurity(
|
const nWeakenHackThreads = Math.ceil(helper.calculateWeakenThreadCountToTargetSecurity(
|
||||||
server.minDifficulty,
|
server.minDifficulty,
|
||||||
increasedSecurityAfterHack, cores));
|
increasedSecurityAfterHack, cores));
|
||||||
|
if(startMoney <= earnMoneyPerCycle){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const nGrowThreads = Math.ceil(helper.calculateGrowThreadCount(hostname, startMoney - earnMoneyPerCycle, startMoney, cores));
|
const nGrowThreads = Math.ceil(helper.calculateGrowThreadCount(hostname, startMoney - earnMoneyPerCycle, startMoney, cores));
|
||||||
const increasedSecurityAfterGrow = helper.calculuateGrowthSecurity(nGrowThreads, cores) + server.minDifficulty;
|
const increasedSecurityAfterGrow = helper.calculuateGrowthSecurity(nGrowThreads, cores) + server.minDifficulty;
|
||||||
|
|
||||||
@ -257,8 +205,11 @@ export function calculateBatchResource(ns: NS, hostname: string, hackThread: num
|
|||||||
increasedSecurityAfterGrow, cores));
|
increasedSecurityAfterGrow, cores));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
earnMoneyPerSec: earnMoneyPerCycle / cycleTime,
|
weakenTime: helper.calculateWeakenTime(server),
|
||||||
earnExpPerSec: earnExpPerCycle / cycleTime,
|
growTime: helper.calculateGrowTime(server),
|
||||||
|
hackTime: helper.calculateHackingTime(server),
|
||||||
|
earnMoneyPerCycle,
|
||||||
|
earnExpPerCycle,
|
||||||
cycleTime,
|
cycleTime,
|
||||||
totalThreadCount: hackThread + nWeakenHackThreads + nGrowThreads + nWeakenGrowThreads,
|
totalThreadCount: hackThread + nWeakenHackThreads + nGrowThreads + nWeakenGrowThreads,
|
||||||
HThreadCount: hackThread,
|
HThreadCount: hackThread,
|
||||||
@ -267,14 +218,163 @@ export function calculateBatchResource(ns: NS, hostname: string, hackThread: num
|
|||||||
GWThreadCount: nWeakenGrowThreads
|
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 {
|
reserve(hostname: string, usableRam: number): void {
|
||||||
GThreadCount: 0,
|
this.resources.push({
|
||||||
HThreadCount: 0,
|
hostname,
|
||||||
GWThreadCount: 0,
|
usableRam,
|
||||||
HWThreadCount: 0,
|
});
|
||||||
|
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));
|
localStorage.setItem(key, JSON.stringify(requests));
|
||||||
}
|
}
|
||||||
|
|
||||||
//export async function batchDaemon(ns: NS): Promise<void> {
|
export function popHWGWRequest(hostname: string): ReserveRequest[]{
|
||||||
// const mgr = new HWGWBatchManager(ns, BATCH_KEY);
|
const key = getKeyOfHWGWBatchManager(hostname);
|
||||||
// for (; ;) {
|
const text = localStorage.getItem(key)
|
||||||
// await mgr.tick();
|
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 { logFile } from "./log";
|
||||||
import { SolveFailError } from "./solve/unsolved";
|
import { SolveFailError } from "./solve/unsolved";
|
||||||
import { RLECompressionSolve, decompressLZSolve, compressLZSolve } from "./solve/compression";
|
import { RLECompressionSolve, decompressLZSolve, compressLZSolve } from "./solve/compression";
|
||||||
|
import {caesarCipherSolve} from "./solve/caesarCipher";
|
||||||
|
|
||||||
export { SolveFailError } from "./solve/unsolved";
|
export { SolveFailError } from "./solve/unsolved";
|
||||||
|
|
||||||
@ -152,13 +153,11 @@ const ContractMAP: {[key:string]:ContractSolver} = {
|
|||||||
"Compression III: LZ Compression": {
|
"Compression III: LZ Compression": {
|
||||||
name: "Compression III: LZ Compression",
|
name: "Compression III: LZ Compression",
|
||||||
solve: compressLZSolve,
|
solve: compressLZSolve,
|
||||||
},/*
|
},
|
||||||
"Encryption I: Caesar Cipher": {
|
"Encryption I: Caesar Cipher": {
|
||||||
name: "Encryption I: Caesar Cipher",
|
name: "Encryption I: Caesar Cipher",
|
||||||
solve() {
|
solve: caesarCipherSolve,
|
||||||
notImplemented();
|
},/*
|
||||||
}
|
|
||||||
},
|
|
||||||
"Encryption II: Vigenère Cipher": {
|
"Encryption II: Vigenère Cipher": {
|
||||||
name: "Encryption II: Vigenère Cipher",
|
name: "Encryption II: Vigenère Cipher",
|
||||||
solve() {
|
solve() {
|
||||||
|
@ -206,6 +206,11 @@ export function canBeAccessBitNode(ns: NS): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getBitNodeMultipliersSafe(ns: NS): BitNodeMultipliers {
|
export function getBitNodeMultipliersSafe(ns: NS): BitNodeMultipliers {
|
||||||
|
const fnName = "getBitNodeMultipliers";
|
||||||
|
const isEnabled = ns.isLogEnabled(fnName);
|
||||||
|
ns.disableLog("disableLog");
|
||||||
|
ns.disableLog("enableLog");
|
||||||
|
ns.disableLog("getBitNodeMultipliers");
|
||||||
try {
|
try {
|
||||||
return ns.getBitNodeMultipliers();
|
return ns.getBitNodeMultipliers();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -213,6 +218,10 @@ export function getBitNodeMultipliersSafe(ns: NS): BitNodeMultipliers {
|
|||||||
return DefaultBitNodeMultipliers;
|
return DefaultBitNodeMultipliers;
|
||||||
}
|
}
|
||||||
throw error;
|
throw error;
|
||||||
|
} finally {
|
||||||
|
if (isEnabled) {
|
||||||
|
ns.enableLog("getBitNodeMultipliers");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +231,10 @@ export class FormulaHelper {
|
|||||||
this.ns = ns;
|
this.ns = ns;
|
||||||
}
|
}
|
||||||
calculateWeakenThreadCountToTargetSecurity(targetSecurity: number, curSecurity: number, cores = 1): number {
|
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);
|
const c = this.ns.weakenAnalyze(1, cores);
|
||||||
return k / c;
|
return k / c;
|
||||||
}
|
}
|
||||||
@ -241,21 +253,31 @@ export class FormulaHelper {
|
|||||||
return ServerWeakenAmount * nThread * coreBonus * mul.ServerWeakenRate;
|
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
|
* @param server
|
||||||
* @returns seconds to complete a weaken operation
|
* @returns milliseconds to complete a weaken operation
|
||||||
*/
|
*/
|
||||||
calculateWeakenTime(server: Server): number {
|
calculateWeakenTime(server: Server): number {
|
||||||
const player = this.ns.getPlayer();
|
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 {
|
calculateGrowTime(server: Server): number {
|
||||||
const player = this.ns.getPlayer();
|
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 {
|
calculateHackingTime(server: Server): number {
|
||||||
const player = this.ns.getPlayer();
|
const player = this.ns.getPlayer();
|
||||||
return calculateHackingTime(server, player);
|
return calculateHackingTime(server, player) * 1000;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Hack
|
* Hack
|
||||||
|
@ -2,7 +2,8 @@ import {NS} from "@ns"
|
|||||||
|
|
||||||
export async function logFile(ns:NS,logFilename:string, data: unknown):Promise<void>{
|
export async function logFile(ns:NS,logFilename:string, data: unknown):Promise<void>{
|
||||||
logFilename = logFilename.replaceAll(" ","-");
|
logFilename = logFilename.replaceAll(" ","-");
|
||||||
logFilename = `/log/${logFilename}${Date.now()}.txt`;
|
logFilename = logFilename.replaceAll(":","-");
|
||||||
|
logFilename = `/log/${logFilename}.txt`;
|
||||||
const loggedData = JSON.stringify(data);
|
const loggedData = JSON.stringify(data);
|
||||||
if(ns.fileExists(logFilename)){
|
if(ns.fileExists(logFilename)){
|
||||||
await ns.write(logFilename,"\n"+loggedData,"a");
|
await ns.write(logFilename,"\n"+loggedData,"a");
|
||||||
|
@ -1,38 +1,185 @@
|
|||||||
import {NS } from "@ns";
|
import {NS} from "@ns";
|
||||||
|
|
||||||
|
/**
|
||||||
type WorkFunc = ()=>void;
|
* tick in scheduler
|
||||||
type WorkChunk = {
|
*/
|
||||||
onStart: WorkFunc[];
|
export interface Tickable {
|
||||||
onFinish: WorkFunc[];
|
/**
|
||||||
}
|
* tick in scheduler
|
||||||
|
*/
|
||||||
interface Tickable {
|
|
||||||
tick(): void;
|
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;
|
ns: NS;
|
||||||
lastCheck: number;
|
lastCheck: number;
|
||||||
pidSet: Map<number, EventTarget>;
|
pidSet: Map<number, Work>;
|
||||||
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 )
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TimerExecutor{
|
|
||||||
ns: NS;
|
|
||||||
constructor(ns: NS){
|
constructor(ns: NS){
|
||||||
this.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
empty(): boolean{
|
||||||
|
return this.pidSet.size === 0;
|
||||||
}
|
}
|
||||||
asdf():{
|
|
||||||
|
|
||||||
|
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);
|
d[j] = Math.min(d[j],d[i]+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(d);
|
|
||||||
return d[arr.length - 1];
|
return d[arr.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function arrayJump2Solve(arr:number[]): number{
|
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]> = [
|
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[]{
|
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 = [
|
export type TestCase = [
|
||||||
Input,
|
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