2022-04-20 11:32:10 -04:00
import { ArgParser } from '/scripts/lib/arg-parser' ;
2022-04-02 12:14:24 -04:00
import { Logger } from '/scripts/lib/logger' ;
2022-04-20 11:32:10 -04:00
import { maxThreads , toCurrency } from '/scripts/lib/utils' ;
import { copyWithDependencies } from "/scripts/copy" ;
2022-04-02 12:14:24 -04:00
/ * *
* Automate the buying & upgrading of servers .
2022-04-20 11:32:10 -04:00
*
* @ param { NS } ns - BitBurner API
2022-04-02 12:14:24 -04:00
* /
export async function main ( ns ) {
// Setup
ns . disableLog ( 'ALL' ) ;
let servers = ns . getPurchasedServers ( ) ;
const logger = new Logger ( ns , [
( ) => ` Server Manager: ${ servers . length } `
] ) ;
2022-04-20 11:32:10 -04:00
const argParser = new ArgParser ( 'server-manager.js' , 'Automate the buying & upgrading of servers. Automatically starts script after purchase. Tail for live updates.' , [
{ name : 'script' , desc : 'Script to copy & execute' , optional : true } ,
{ name : 'args' , desc : 'Arguments for script. Forward the discovered server with: {{SERVER}}' , optional : true , extras : true } ,
2022-04-02 12:14:24 -04:00
{ name : 'balance' , desc : 'Prevent spending bellow point' , flags : [ '-b' , '--balance' ] , default : 0 } ,
2022-04-20 11:32:10 -04:00
{ name : 'cpu' , desc : 'Number of CPU threads to start script with, will use maximum if not specified' , flags : [ '-c' , '--cpu' ] , default : false } ,
2022-04-02 12:14:24 -04:00
{ name : 'limit' , desc : 'Limit the number of servers that can be purchased, defaults to 25' , flags : [ '-l' , '--limit' ] , default : 25 } ,
{ name : 'ram' , desc : 'Amount of RAM to purchase new servers with, defaults to 8 GB' , flags : [ '-r' , '--ram' ] , default : 8 } ,
{ name : 'sleep' , desc : 'Amount of time to wait between purchases, defaults to 1 (second)' , flags : [ '-s' , '--sleep' ] , default : 1 }
] ) ;
2022-04-20 11:32:10 -04:00
const args = argParser . parse ( ns . args ) ;
2022-04-02 12:14:24 -04:00
const serverPrefix = 'botnet_'
const maxRam = ns . getPurchasedServerMaxRam ( ) ;
const minRamCost = ns . getPurchasedServerCost ( args [ 'ram' ] ) ;
2022-04-20 11:32:10 -04:00
async function startScript ( server ) {
await copyWithDependencies ( ns , args [ 'script' ] , server ) ;
const threads = args [ 'cpu' ] || maxThreads ( ns , args [ 'script' ] , server ) || 1 ;
const pid = ns . exec ( args [ 'script' ] , server , threads , ... args [ 'args' ] ) ;
logger . log ( ` Starting " ${ args [ 'script' ] } " with ${ threads } thread ${ threads > 1 ? 's' : '' } ` ) ;
logger [ pid == - 1 ? 'warn' : 'log' ] ( pid == - 1 ? 'Done!' : 'Failed to start' ) ;
}
2022-04-02 12:14:24 -04:00
// Help
2022-04-20 11:32:10 -04:00
if ( args [ 'help' ] || args [ '_error' ] . length )
return ns . tprint ( argParser . help ( args [ 'help' ] ? null : args [ '_error' ] [ 0 ] , args [ '_command' ] ) ) ;
2022-04-02 12:14:24 -04:00
2022-04-20 11:32:10 -04:00
// Main loop
// noinspection InfiniteLoopJS
2022-04-02 12:14:24 -04:00
while ( true ) {
servers = ns . getPurchasedServers ( ) ;
const balance = ns . getServerMoneyAvailable ( 'home' ) ;
// Purchase new server if we can afford it
if ( servers . length < args [ 'limit' ] && balance - minRamCost > args [ 'balance' ] ) {
2022-04-20 11:32:10 -04:00
logger . log ( ` Buying server ( ${ args [ 'ram' ] } GB): ${ toCurrency ( minRamCost ) } ` ) ;
2022-04-02 12:14:24 -04:00
ns . purchaseServer ( ` ${ serverPrefix } ${ servers . length } ` , args [ 'ram' ] ) ;
2022-04-20 11:32:10 -04:00
// Run the script if requested
if ( args [ 'script' ] ) await startScript ( ` ${ serverPrefix } ${ servers . length - 1 } ` ) ;
2022-04-02 12:14:24 -04:00
} else { // Check for upgrades
2022-04-20 11:32:10 -04:00
let upgrades = servers . map ( server => {
2022-04-02 12:14:24 -04:00
// Calculate next RAM upgrades (must be a power of two: 2, 4, 8, 16, 32...)
2022-04-20 11:32:10 -04:00
let ram = Math . pow ( 2 , Math . log2 ( ns . getServerMaxRam ( server ) ) + 1 ) ;
2022-04-02 12:14:24 -04:00
if ( ram > maxRam ) ram = null ;
return {
server ,
ram ,
cost : ram ? ns . getPurchasedServerCost ( ram ) : null
}
} ) ;
2022-04-20 11:32:10 -04:00
upgrades = upgrades . sort ( ( a , b ) => { // Sort by price
2022-04-02 12:14:24 -04:00
if ( a . cost < b . cost ) return 1 ;
if ( a . cost < b . cost ) return - 1 ;
return 0 ;
} ) ;
// Do the cheapest upgrade if we can afford it
const upgrade = upgrades [ 0 ] ;
if ( upgrade && ! ! upgrade . ram && balance - upgrade . cost > args [ 'balance' ] ) {
2022-04-20 11:32:10 -04:00
logger . log ( ` Upgrading ${ upgrade . server } : ${ upgrade . ram } GB / ${ toCurrency ( upgrade . cost ) } ` ) ;
2022-04-02 12:14:24 -04:00
ns . killall ( upgrade . server ) ;
ns . deleteServer ( upgrade . server ) ;
ns . purchaseServer ( upgrade . server , upgrade . ram ) ;
2022-04-20 11:32:10 -04:00
// Run the script if requested
if ( args [ 'script' ] ) await startScript ( upgrade . server ) ;
2022-04-02 12:14:24 -04:00
}
}
await ns . sleep ( args [ 'sleep' ] * 1000 ) ;
}
}