summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJulien Dessaux2023-05-25 01:20:56 +0200
committerJulien Dessaux2023-05-25 01:20:56 +0200
commitb1157af9cd66878623ad1f9fadac862e4990901c (patch)
tree3e95713b4ede9d292a2bf00af88f36e7cbe12e0d /lib
parentRewrote the api rate limiter with promises instead of callbacks (diff)
downloadspacetraders-b1157af9cd66878623ad1f9fadac862e4990901c.tar.gz
spacetraders-b1157af9cd66878623ad1f9fadac862e4990901c.tar.bz2
spacetraders-b1157af9cd66878623ad1f9fadac862e4990901c.zip
Updated the lib for the new api
Diffstat (limited to 'lib')
-rw-r--r--lib/agent.js157
-rw-r--r--lib/api.js4
-rw-r--r--lib/contracts.js17
-rw-r--r--lib/ships.js63
4 files changed, 180 insertions, 61 deletions
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}`});
}