-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathd_tasker.js
More file actions
180 lines (159 loc) · 5.56 KB
/
Copy pathd_tasker.js
File metadata and controls
180 lines (159 loc) · 5.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/** @param {NS} ns **/
/*
Project Object Contract
id: project id
target: target hostname
type: hack, grow, weak, etc.
threads: int
results: []
tasks: []
*/
import { generateId, allServers, getConfig, maxThreads, handlePort, autoDiscovery } from "util.js";
function convertToFollowUp(prj, newThreads, keepId){
return {
id: keepId? prj.id : `fup-${generateId(16)}`,
threads: newThreads,
target: prj.target,
type: prj.type,
originalProjectId: prj.originalProjectId || prj.id
}
}
export async function main(ns) {
const ALL_SERVERS = allServers(ns, true);
const trackedProjects = [];
const projectQueue = [];
// clear any task finishes
ns.clearPort(2);
function getAvailableRAM(host){
let RAM = ns.getServerMaxRam(host);
let used = ns.getServerUsedRam(host);
return RAM - used;
}
function getTaskableServers(){
const config = getConfig(ns);
return ALL_SERVERS.map((s) => {
let reserve = config.reservedRAM[s] || 0;
if(reserve == "ALL"){ return {host: s, aRAM: 0}; }
let available = getAvailableRAM(s) - reserve;
return {host: s, aRAM: available};
})
.filter((s) => {
return s.aRAM > 2;
})
.sort((a,b) => {
return b.aRAM - a.aRAM;
});
}
async function finishProject(prj){
let pid = prj.originalProjectId || prj.id;
let result = prj.results.reduce((pv,cv)=>{ return pv+cv; }, 0);
await ns.writePort(3, pid);
if(prj.type == "pwn"){
ns.toast(`${prj.target} pwnd!`, "error");
}
else if(prj.type == "hack"){
ns.toast(`${prj.target} hacked for ${ns.nFormat(result, "0.000a")}!`, "success");
}
else if(prj.type == "grow"){
ns.toast(`${prj.target} grown by ${result.toFixed(2)}!`, "info");
}
else if(prj.type == "weak"){
ns.toast(`${prj.target} weakened by ${result.toFixed(2)}!`, "warning");
}
}
async function handleTaskFinish(ns, pd){
let pData = JSON.parse(pd);
let projectIndex = trackedProjects.findIndex((prj) => {
return prj.id == pData.projectId;
});
if(projectIndex > -1){
let tProj = trackedProjects[projectIndex];
tProj.tasks.splice(tProj.tasks.indexOf(pData.taskId), 1);
tProj.results.push(pData.result);
if(tProj.tasks.length == 0){
// project is finished
let cProj = trackedProjects.splice(projectIndex, 1)[0];
if(!cProj.hasFollowup){
await finishProject(cProj);
}
}
}
}
while(true){
const CONFIG = getConfig(ns);
const INTERVAL_MS = CONFIG.daemonInterval;
const INTERNAL_INTERVAL_MS = Math.ceil(INTERVAL_MS / 10);
// auto-discover
await autoDiscovery(ns, ALL_SERVERS);
// clear any finishes
await handlePort(ns, 2, INTERNAL_INTERVAL_MS, handleTaskFinish);
// start a list of projects to start
let projectsToStart = [];
// check for queued projects
if(projectQueue.length > 0){
projectsToStart.push(...projectQueue.splice(0, projectQueue.length));
}
// check for new projects
async function handleProjectStart(ns, pd){
let project = JSON.parse(pd);
projectsToStart.push(project);
}
await handlePort(ns, 1, INTERNAL_INTERVAL_MS, handleProjectStart);
// we have projects to start
let currentProject = projectsToStart.shift();
while(currentProject){
// spin up this project
if(!currentProject.tasks){ currentProject.tasks = []; }
if(!currentProject.results){ currentProject.results = []; }
// determine task script
let taskScript = false;
if(currentProject.type == "hack"){ taskScript = "t_hack.js"; }
else if(currentProject.type == "grow"){ taskScript = "t_grow.js"; }
else if(currentProject.type == "weak"){ taskScript = "t_weak.js"; }
else if(currentProject.type == "pwn"){ taskScript = "t_pwn.js"; }
// add more here later
else {
// unknown kick it back to the queue for now
projectQueue.push(currentProject);
}
// get taskScript RAM size
const taskScriptRAM = ns.getScriptRam(taskScript);
const taskables = getTaskableServers();
let filledThreads = 0;
while(filledThreads < currentProject.threads && taskables.length > 0){
const ts = taskables.shift();
const mt = maxThreads(taskScriptRAM, ts.aRAM);
const taskThreads = Math.min(mt, currentProject.threads);
const task = {host: ts.host, threads: taskThreads, id: generateId(16)}
currentProject.tasks.push(task);
filledThreads += taskThreads;
await ns.sleep(INTERNAL_INTERVAL_MS);
}
if(filledThreads == 0){
// no taskables, back to the queue
projectQueue.push(convertToFollowUp(currentProject, currentProject.threads, true));
}
else {
if(filledThreads < currentProject.threads){
projectQueue.push(convertToFollowUp(currentProject, currentProject.threads - filledThreads));
currentProject.hasFollowup = true;
}
// track this project
trackedProjects.push(currentProject);
// start the tasks
for(var i in currentProject.tasks){
const ct = currentProject.tasks[i];
const argsArr = ["--target", currentProject.target, "--taskId", ct.id, "--projectId", currentProject.id];
if(ct.host != "home"){
await ns.scp(taskScript, "home", ct.host);
}
await ns.exec(taskScript, ct.host, ct.threads, ...argsArr);
currentProject.tasks[i] = ct.id;
}
}
currentProject = projectsToStart.shift();
await ns.sleep(INTERNAL_INTERVAL_MS);
}
await ns.sleep(INTERVAL_MS);
}
}