From b1157af9cd66878623ad1f9fadac862e4990901c Mon Sep 17 00:00:00 2001 From: Julien Dessaux Date: Thu, 25 May 2023 01:20:56 +0200 Subject: Updated the lib for the new api --- lib/agent.js | 157 ++++++++++++++++++++++++++++++++++++++++--------------- lib/api.js | 4 ++ lib/contracts.js | 17 ++++++ lib/ships.js | 63 +++++++++++++++------- 4 files changed, 180 insertions(+), 61 deletions(-) create mode 100644 lib/contracts.js (limited to 'lib') diff --git a/lib/agent.js b/lib/agent.js index ca9da0d..69e64a5 100644 --- a/lib/agent.js +++ b/lib/agent.js @@ -1,52 +1,124 @@ import { registerAgent } from '../database/config.js'; import * as api from './api.js'; +import * as contracts from './contracts.js'; import * as ships from './ships.js'; +import * as systems from './systems.js'; -// This starts an extraction loop with a ship which ends when the ship's cargo is at least 90% full with only one desired good -// ctx must must have two attributes: `ship` and `good` -export function extract(ctx, response) { - if (response !== undefined) { - if (response.error !== undefined) { - switch(response.error.code) { - case 4000: // ship is on cooldown - setTimeout(extract, response.error.data.cooldown.remainingSeconds * 1000, ctx); - return; - case 4228: // ship is full. Running the ship inventory function to list the cargo so that know if we need to sell - ships.ship({ship: ctx.ship, next:{action: extract, ship: ctx.ship, good: ctx.good}}); - return; - default: - throw response; - } - } - if (response.data.extraction !== undefined && response.data.extraction.yield !== undefined) { // yield won't be defined if we reached this point from an inventory request - console.log(`${ctx.ship}: extracted ${response.data.extraction.yield.units} of ${response.data.extraction.yield.symbol}`); - } - if (response.data.cargo !== undefined && response.data.cargo.capacity * 0.9 <= response.data.cargo.units) { // > 90% full - const good = response.data.cargo.inventory.filter(i => i.symbol === ctx.good)[0]; - const inventory = response.data.cargo.inventory.filter(i => i.symbol !== ctx.good); - if (good?.units >= response.data.cargo.capacity * 0.9) { // > 90% full - console.log(`ship's cargo is full with ${response.data.cargo.units} of ${ctx.good}!`); - return; - } - let actions = [{ action: ships.dock, ship: ctx.ship }]; - inventory.forEach(i => actions.push({action: ships.sell, ship: ctx.ship, good: i.symbol, units: i.units})); - actions.push({action: ships.orbit, ship: ctx.ship}); - actions.push({action: extract, ship: ctx.ship, good: ctx.good}); - api.chain(actions); - return; - } else { // we need to mine more - if (response.data.cooldown) { // we are on cooldown, call ourselves again in a moment - setTimeout(extract, response.data.cooldown.remainingSeconds * 1000, ctx); - return; - } - } - } - ships.extract({ship: ctx.ship, good: ctx.good, next: { action: extract, ship: ctx.ship, good: ctx.good }}); -} +// This starts a delivery loop with a ship which ends when the delivery is fullfilled +// ctx must must have multiple attributes: `ship`, `contract` (with the contractId), `good`, `destination` (the delivery waypoint), `field` (the asteroid field waypoint). The ship needs to be orbiting the asteroid field. +//export function deliver(ctx, response) { +// let next = {...ctx}; +// next.action = deliver; // calling ourselves after the action is a good default +// if (response !== undefined) { +// if (response.error !== undefined) { +// console.log("ctx:", JSON.stringify(ctx, null, 2)); +// console.log("response:", JSON.stringify(response, null, 2)); +// switch(response.error.code) { +// case 4000: // ship is on cooldown +// setTimeout(deliver, response.error.data.cooldown.remainingSeconds * 1000, ctx); +// return; +// case 4228: // ship cannot extract because it is full. Running the ship inventory function to list the cargo so that we know if we need to sell +// ships.ship({ship: ctx.ship, next: next}); +// return; +// default: // yet unhandled error +// throw response; +// } +// } +// if (response.data.extraction !== undefined && response.data.extraction.yield !== undefined) { // yield won't be defined if we reached this point from an inventory request +// console.log(`${ctx.ship}: extracted ${response.data.extraction.yield.units} of ${response.data.extraction.yield.symbol}`); +// } +// if (response.data.cargo !== undefined && response.data.cargo.capacity * 0.9 <= response.data.cargo.units) { // > 90% full +// const good = response.data.cargo.inventory.filter(i => i.symbol === ctx.good)[0]; +// const inventory = response.data.cargo.inventory.filter(i => i.symbol !== ctx.good); +// if (good?.units >= response.data.cargo.capacity * 0.9) { // > 90% full +// console.log(`ship's cargo is full with ${good.units} of ${ctx.good}!`); +// next.units = good.units; // set the unit property so that we know how much to deliver +// ships.navigate({ship: ctx.ship, waypoint: ctx.destination, next: next}); +// } +// let actions = [{ action: ships.dock, ship: ctx.ship }]; +// inventory.forEach(i => actions.push({action: ships.sell, ship: ctx.ship, good: i.symbol, units: i.units})); +// actions.push({action: ships.orbit, ship: ctx.ship}); +// actions.push({action: deliver, ship: ctx.ship, good: ctx.good}); +// api.chain(actions); +// return; +// } else if (response.data.nav !== undefined) { // we are moving +// const delay = new Date(response.data.nav.route.arrival) - new Date(); +// console.log(new Date(response.data.nav.route.arrival), new Date(), delay); +// if (delay > 0) { // the ship did not arrive yet, we wait +// setTimeout(deliver, delay+1000, ctx, response); +// return; +// } +// if (response.data.nav.route.destination.symbol === ctx.destination) { // we arrived to the delivery point +// api.chain([{ action: ships.dock, ship: ctx.ship }, +// { action: ships.refuel, ship: ctx.ship }, +// { action: ships.deliver, contract: ctx.contract, ship: ctx.ship, good: ctx.good, units: ctx.units }, +// { action: ships.navigate, ship: ctx.ship, waypoint: ctx.field, next: next }]); +// return; +// } else if (next.units !== undefined) { // we arrived to the asteroid field +// delete next.units; // remove the unit property +// api.chain([{ action: ships.dock, ship: ctx.ship }, +// { action: ships.refuel, ship: ctx.ship }, +// { action: ships.orbit, ship: ctx.ship, next: next }]); // TODO we are on cooldown and cannot mine right now +// return; +// } +// } else { // we need to mine more +// if (response.data.cooldown) { // we are on cooldown, call ourselves again in a moment +// setTimeout(deliver, response.data.cooldown.remainingSeconds * 1000, ctx); +// return; +// } +// } +// } +// ships.extract({ship: ctx.ship, good: ctx.good, next: next}); +//} +// +//// This starts an extraction loop with a ship which ends when the ship's cargo is at least 90% full with only one desired good +//// ctx must must have two attributes: `ship` and `good`. The ship needs to be orbiting an asteroid field +//export function extract(ctx, response) { +// if (response !== undefined) { +// if (response.error !== undefined) { +// switch(response.error.code) { +// case 4000: // ship is on cooldown +// setTimeout(extract, response.error.data.cooldown.remainingSeconds * 1000, ctx); +// return; +// case 4228: // ship is full. Running the ship inventory function to list the cargo so that know if we need to sell +// ships.ship({ship: ctx.ship, next:{action: extract, ship: ctx.ship, good: ctx.good}}); +// return; +// default: +// throw response; +// } +// } +// if (response.data.extraction !== undefined && response.data.extraction.yield !== undefined) { // yield won't be defined if we reached this point from an inventory request +// console.log(`${ctx.ship}: extracted ${response.data.extraction.yield.units} of ${response.data.extraction.yield.symbol}`); +// } +// if (response.data.cargo !== undefined && response.data.cargo.capacity * 0.9 <= response.data.cargo.units) { // > 90% full +// const good = response.data.cargo.inventory.filter(i => i.symbol === ctx.good)[0]; +// const inventory = response.data.cargo.inventory.filter(i => i.symbol !== ctx.good); +// if (good?.units >= response.data.cargo.capacity * 0.9) { // > 90% full +// console.log(`ship's cargo is full with ${response.data.cargo.units} of ${ctx.good}!`); +// return; +// } +// let actions = [{ action: ships.dock, ship: ctx.ship }]; +// inventory.forEach(i => actions.push({action: ships.sell, ship: ctx.ship, good: i.symbol, units: i.units})); +// actions.push({action: ships.orbit, ship: ctx.ship}); +// actions.push({action: extract, ship: ctx.ship, good: ctx.good}); +// api.chain(actions); +// return; +// } else { // we need to mine more +// if (response.data.cooldown) { // we are on cooldown, call ourselves again in a moment +// setTimeout(extract, response.data.cooldown.remainingSeconds * 1000, ctx); +// return; +// } +// } +// } +// ships.extract({ship: ctx.ship, good: ctx.good, next: { action: extract, ship: ctx.ship, good: ctx.good }}); +//} // This function inits the database in case we have an already registered game export function init(symbol, faction, token) { registerAgent(symbol, faction, token); + // TODO ships + // TODO contract + // TODO agent } // This function registers then inits the database @@ -67,6 +139,9 @@ export function register(symbol, faction) { .then(response => { console.log(JSON.stringify(response, null, 2)); init(symbol, faction, response.data.token); + // TODO ship + // TODO contract + // TODO agent }) .catch(err => console.error(err)); } diff --git a/lib/api.js b/lib/api.js index bbb2977..abcd85d 100644 --- a/lib/api.js +++ b/lib/api.js @@ -69,3 +69,7 @@ export function debugLog(ctx) { console.log(`--- ${Date()} -----------------------------------------------------------------------------`); console.log(JSON.stringify(ctx, null, 2)); } + +export function sleep(delay) { + return new Promise((resolve) => setTimeout(resolve, delay)) +} diff --git a/lib/contracts.js b/lib/contracts.js new file mode 100644 index 0000000..9494595 --- /dev/null +++ b/lib/contracts.js @@ -0,0 +1,17 @@ +import * as api from './api.js'; + +export async function accept(ctx) { + return await api.send({endpoint: `/my/contracts/${ctx.id}/accept`, method: 'POST'}); +} + +export async function contracts() { + return await api.send({endpoint: '/my/contracts'}); +} + +export async function deliver(ctx) { + return await api.send({ endpoint: `/my/contracts/${ctx.contract}/deliver`, method: 'POST', payload: { + shipSymbol: ctx.ship, + tradeSymbol: ctx.good, + units: ctx.units, + }}); +} diff --git a/lib/ships.js b/lib/ships.js index e536e73..9a57c12 100644 --- a/lib/ships.js +++ b/lib/ships.js @@ -1,35 +1,58 @@ import * as api from './api.js'; -export function extract(ctx) { - console.log(`${ctx.ship}: extracting`); - api.send({endpoint: `/my/ships/${ctx.ship}/extract`, method: 'POST', next: ctx.next}); +export async function extract(ctx) { + const response = await api.send({endpoint: `/my/ships/${ctx.ship}/extract`, method: 'POST'}); + if (response.error !== undefined) { + switch(response.error.code) { + case 4000: // ship is on cooldown + await api.sleep(response.error.data.remainingSeconds * 1000); + return extract(ctx); + case 4228: // ship is full + return null; + default: // yet unhandled error + throw response; + } + } + return response; } -export function dock(ctx) { - console.log(`${ctx.ship}: docking`); - api.send({endpoint: `/my/ships/${ctx.ship}/dock`, method: 'POST', next: ctx.next}); +export async function dock(ctx) { + const response = await api.send({endpoint: `/my/ships/${ctx.ship}/dock`, method: 'POST'}); + if (response.error !== undefined) { + switch(response.error.code) { + case 4214: // ship is in transit + await api.sleep(response.error.data.secondsToArrival * 1000); + return dock(ctx); + default: // yet unhandled error + throw response; + } + } + return response; } -export function navigate(ctx) { - console.log(`${ctx.ship}: navigating to ${ctx.waypoint}`); - api.send({endpoint: `/my/ships/${ctx.ship}/navigate`, method: 'POST', payload: { waypointSymbol: ctx.waypoint }, next: ctx.next}); +export async function navigate(ctx) { + return await api.send({endpoint: `/my/ships/${ctx.ship}/navigate`, method: 'POST', payload: { waypointSymbol: ctx.waypoint }}); } -export function orbit(ctx) { - console.log(`${ctx.ship}: orbiting`); - api.send({endpoint: `/my/ships/${ctx.ship}/orbit`, method: 'POST', next: ctx.next}); +export async function orbit(ctx) { + return await api.send({endpoint: `/my/ships/${ctx.ship}/orbit`, method: 'POST'}); } -export function refuel(ctx) { - console.log(`${ctx.ship}: refueling`); - api.send({endpoint: `/my/ships/${ctx.ship}/refuel`, method: 'POST', next: ctx.next}); +export async function purchase(ctx) { + return await api.send({endpoint: '/my/ships', method: 'POST', payload: { + shipType: ctx.shipType, + waypointSymbol: ctx.waypoint, + }}); } -export function sell(ctx) { - console.log(`${ctx.ship}: selling ${ctx.units} of ${ctx.good}`); - api.send({endpoint: `/my/ships/${ctx.ship}/sell`, method: 'POST', payload: { symbol: ctx.good, units: ctx.units }, next: ctx.next}); +export async function refuel(ctx) { + return await api.send({endpoint: `/my/ships/${ctx.ship}/refuel`, method: 'POST'}); } -export function ship(ctx) { - api.send({endpoint: `/my/ships/${ctx.ship}`, next: ctx.next}); +export async function sell(ctx) { + return await api.send({endpoint: `/my/ships/${ctx.ship}/sell`, method: 'POST', payload: { symbol: ctx.good, units: ctx.units }}); +} + +export async function ship(ctx) { + return await api.send({endpoint: `/my/ships/${ctx.ship}`}); } -- cgit v1.2.3