diff options
author | Julien Dessaux | 2024-04-05 00:42:30 +0200 |
---|---|---|
committer | Julien Dessaux | 2024-04-07 23:01:52 +0200 |
commit | 234770b611df32178382b557df396db220070a7f (patch) | |
tree | 8c768846716eaf892ff75abe84d0f5c00e8519ff /nodejs | |
parent | [node] Fixed basic procurement trading loop (diff) | |
download | spacetraders-234770b611df32178382b557df396db220070a7f.tar.gz spacetraders-234770b611df32178382b557df396db220070a7f.tar.bz2 spacetraders-234770b611df32178382b557df396db220070a7f.zip |
[node] Big Ships lib refactoring
Diffstat (limited to '')
-rw-r--r-- | nodejs/automation/contracting.ts | 32 | ||||
-rw-r--r-- | nodejs/automation/exploration.ts | 2 | ||||
-rw-r--r-- | nodejs/automation/init.ts | 20 | ||||
-rw-r--r-- | nodejs/automation/mining.ts | 18 | ||||
-rw-r--r-- | nodejs/automation/selling.ts | 25 | ||||
-rw-r--r-- | nodejs/database/agents.ts | 2 | ||||
-rw-r--r-- | nodejs/database/contracts.ts | 2 | ||||
-rw-r--r-- | nodejs/database/markets.ts | 2 | ||||
-rw-r--r-- | nodejs/database/ships.ts | 57 | ||||
-rw-r--r-- | nodejs/database/systems.ts | 2 | ||||
-rw-r--r-- | nodejs/lib/api.ts | 35 | ||||
-rw-r--r-- | nodejs/lib/contracts.ts | 43 | ||||
-rw-r--r-- | nodejs/lib/errors.ts | 35 | ||||
-rw-r--r-- | nodejs/lib/ships.ts | 405 | ||||
-rw-r--r-- | nodejs/lib/systems.ts | 32 | ||||
-rw-r--r-- | nodejs/lib/types.ts | 145 | ||||
-rw-r--r-- | nodejs/lib/utils.ts | 2 | ||||
-rwxr-xr-x | nodejs/main.ts | 6 | ||||
-rw-r--r-- | nodejs/model/agent.ts | 8 | ||||
-rw-r--r-- | nodejs/model/api.ts | 31 | ||||
-rw-r--r-- | nodejs/model/cargo.ts | 17 | ||||
-rw-r--r-- | nodejs/model/common.ts | 5 | ||||
-rw-r--r-- | nodejs/model/contract.ts | 22 | ||||
-rw-r--r-- | nodejs/model/errors.ts | 8 | ||||
-rw-r--r-- | nodejs/model/market.ts | 19 | ||||
-rw-r--r-- | nodejs/model/ship.ts | 62 | ||||
-rw-r--r-- | nodejs/model/system.ts | 30 |
27 files changed, 489 insertions, 578 deletions
diff --git a/nodejs/automation/contracting.ts b/nodejs/automation/contracting.ts index fa9a4c4..96f9106 100644 --- a/nodejs/automation/contracting.ts +++ b/nodejs/automation/contracting.ts @@ -1,32 +1,28 @@ -import { Contract } from '../model/contract.ts'; -import { Ship } from '../model/ship.ts'; +import { Contract } from '../lib/types.ts'; +import { Ship } from '../lib/ships.ts'; import * as mining from './mining.js'; import * as selling from './selling.js'; import * as dbContracts from '../database/contracts.ts'; -import * as dbShips from '../database/ships.ts'; -import * as api from '../lib/api.ts'; import * as contracts from '../lib/contracts.ts'; -import * as libShips from '../lib/ships.ts'; import * as libSystems from '../lib/systems.ts'; import * as systems from '../lib/systems.ts'; import * as utils from '../lib/utils.ts'; -export async function init(): Promise<void> { - const ship = dbShips.getShips()[0]; // This should always be the command ship +export async function run(ship: Ship): Promise<void> { while(true) { // we use the fact that there can only be at most one active contract at a time const contracts = dbContracts.getContracts().filter(c => !c.fulfilled); let contract: Contract; if (contracts.length === 0) { - contract = await libShips.negotiate(ship); + contract = await ship.negotiate(); } else { contract = contracts[0]; } - await run(contract, ship); - await libShips.negotiate(ship); + await runOne(contract, ship); + await ship.negotiate(); } } -async function run(contract: Contract, ship: Ship): Promise<void> { +async function runOne(contract: Contract, ship: Ship): Promise<void> { await contracts.accept(contract); switch(contract.type) { case 'PROCUREMENT': @@ -47,24 +43,23 @@ async function runOreProcurement(contract: Contract, ship: Ship): Promise<void> const asteroids = await systems.type(ship.nav.systemSymbol, 'ENGINEERED_ASTEROID'); const asteroidSymbol = asteroids[0].symbol; while (!contract.fulfilled) { - ship = dbShips.getShip(ship.symbol); const goodCargo = ship.cargo.inventory.filter(i => i.symbol === wantedCargo)[0] // what we do depends on where we are switch (ship.nav.waypointSymbol) { case asteroidSymbol: await mining.mineUntilFullFor(contract, ship, asteroidSymbol); - await libShips.navigate(ship, deliveryPoint); + await ship.navigate(deliveryPoint); break; case deliveryPoint: if (goodCargo !== undefined) { // we could be here if a client restart happens right after selling before we navigate away contract = await contracts.deliver(contract, ship); if (contract.fulfilled) return; } - await libShips.navigate(ship, asteroidSymbol); + await ship.navigate(asteroidSymbol); break; default: await selling.sell(ship, wantedCargo); - await libShips.navigate(ship, asteroidSymbol); + await ship.navigate(asteroidSymbol); } } } @@ -74,7 +69,6 @@ async function runTradeProcurement(contract: Contract, ship: Ship): Promise<void const deliveryPoint = deliver.destinationSymbol; const wantedCargo = deliver.tradeSymbol; while (!contract.fulfilled) { - ship = dbShips.getShip(ship.symbol); const goodCargo = ship.cargo.inventory.filter(i => i.symbol === wantedCargo)[0] // make sure we are not carrying useless stuff await selling.sell(ship, wantedCargo); @@ -122,14 +116,14 @@ async function runTradeProcurement(contract: Contract, ship: Ship): Promise<void throw `runTradeProcurement failed, no market exports or exchanges ${wantedCargo}`; } // go buy what we need - await libShips.navigate(ship, buyingPoint); + await ship.navigate(buyingPoint); const units = Math.min( deliver.unitsRequired - deliver.unitsFulfilled, ship.cargo.capacity - ship.cargo.units, ); - await libShips.buy(ship, wantedCargo, units); + await ship.purchase(wantedCargo, units); // then make a delivery - await libShips.navigate(ship, deliveryPoint); + await ship.navigate(deliveryPoint); contract = await contracts.deliver(contract, ship); if (contract.fulfilled) return; } diff --git a/nodejs/automation/exploration.ts b/nodejs/automation/exploration.ts index 67fbfe4..9ea0a5b 100644 --- a/nodejs/automation/exploration.ts +++ b/nodejs/automation/exploration.ts @@ -1,6 +1,6 @@ import db from '../database/db.ts'; import * as dbSystems from '../database/systems.ts'; -import { System } from '../model/system.ts'; +import { System } from '../lib/types.ts'; import * as api from '../lib/api.ts'; export async function init(): Promise<void> { diff --git a/nodejs/automation/init.ts b/nodejs/automation/init.ts index 79c5e39..1e8ea72 100644 --- a/nodejs/automation/init.ts +++ b/nodejs/automation/init.ts @@ -1,16 +1,16 @@ import * as dbAgents from '../database/agents.ts'; import * as db from '../database/db.ts'; import * as dbContracts from '../database/contracts.ts'; -import * as dbShips from '../database/ships.ts'; import * as dbTokens from '../database/tokens.ts'; -import { Agent } from '../model/agent.ts'; -import { Response } from '../model/api.ts'; -import { Contract } from '../model/contract.ts'; -import { Ship } from '../model/ship.ts'; -import * as api from '../lib/api.ts'; -//import * as agents from '../lib/angent.ts'; +import { + Response, +} from '../lib/api.ts'; +import { + Agent, + Contract, +} from '../lib/types.ts'; +import { Ship } from '../lib/ships.ts'; import * as libContracts from '../lib/contracts.ts'; -import * as libShips from '../lib/ships.ts'; const symbol = process.env.NODE_ENV === 'test' ? 'ADYXAX-0' : 'ADYXAX-JS'; @@ -32,7 +32,6 @@ export async function init(): Promise<void> { case 4111: // 4111 means the agent symbol has already been claimed so no server reset happened // TODO await agents.agents(); await libContracts.getContracts(); - await libShips.getShips(); return; default: throw json; @@ -42,7 +41,4 @@ export async function init(): Promise<void> { dbTokens.addToken(json.data.token); dbAgents.addAgent(json.data.agent); dbContracts.setContract(json.data.contract); - dbShips.setShip(json.data.ship); - // Temporary fix to fetch the data on the startup probe - await libShips.getShips(); } diff --git a/nodejs/automation/mining.ts b/nodejs/automation/mining.ts index 272c39a..07fa19b 100644 --- a/nodejs/automation/mining.ts +++ b/nodejs/automation/mining.ts @@ -1,11 +1,8 @@ import * as selling from './selling.js'; import * as dbContracts from '../database/contracts.js'; -import * as dbShips from '../database/ships.js'; -import * as api from '../lib/api.js'; -import * as libShips from '../lib/ships.js'; -import * as utils from '../lib/utils.js'; -import { Contract } from '../model/contract.ts'; -import { Ship } from '../model/ship.ts'; +import { Ship } from '../lib/ships.js'; +import { Contract } from '../lib/types.ts'; +import { categorizeCargo } from '../lib/utils.ts'; export async function mineUntilFullFor(contract: Contract, ship: Ship, asteroidSymbol: string): Promise<void> { // TODO find a good asteroid @@ -13,21 +10,20 @@ export async function mineUntilFullFor(contract: Contract, ship: Ship, asteroidS await mineUntilFull(ship); contract = dbContracts.getContract(contract.id); const deliver = contract.terms.deliver[0]; - ship = dbShips.getShip(ship.symbol); - const cargo = utils.categorizeCargo(ship.cargo, deliver.tradeSymbol); + const cargo = categorizeCargo(ship.cargo, deliver.tradeSymbol); const wantedUnits = Object.values(cargo.wanted).reduce((acc, e) => acc += e, 0); // > 90% full of the valuable goods ? Or just have enough for the contract? if (wantedUnits >= ship.cargo.capacity * 0.9 || cargo.wanted[deliver.tradeSymbol] >= deliver.unitsRequired - deliver.unitsFulfilled) return; // we are full but need to sell junk await selling.sell(ship, deliver.tradeSymbol); - await libShips.navigate(ship, asteroidSymbol); + await ship.navigate(asteroidSymbol); } } async function mineUntilFull(ship: Ship): Promise<void> { - while (!libShips.isFull(ship)) { - await libShips.extract(ship); + while (!ship.isFull()) { + await ship.extract(); } } diff --git a/nodejs/automation/selling.ts b/nodejs/automation/selling.ts index 04b0e9d..bc586fe 100644 --- a/nodejs/automation/selling.ts +++ b/nodejs/automation/selling.ts @@ -1,29 +1,26 @@ import * as dbMarkets from '../database/markets.ts'; -import * as dbShips from '../database/ships.ts'; -import * as api from '../lib/api.ts'; -import * as libShips from '../lib/ships.ts'; import * as libSystems from '../lib/systems.ts'; -import * as utils from '../lib/utils.ts'; -import { CargoManifest } from '../model/cargo.ts'; -import { CommonThing } from '../model/common.ts'; -import { Ship } from '../model/ship.ts'; +import { categorizeCargo } from '../lib/utils.ts'; +import { Ship } from '../lib/ships.ts'; +import { + CargoManifest, + CommonThing, +} from '../lib/types.ts'; // example ctx { ship: {XXX}, keep: 'SILVER_ORE' } export async function sell(ship: Ship, good: string): Promise<Ship> { outer: while(true) { - ship = dbShips.getShip(ship.symbol); // first lets see what we want to sell - let cargo = utils.categorizeCargo(ship.cargo, good); + let cargo = categorizeCargo(ship.cargo, good); // get the marketdata from our location const market = await libSystems.market(ship.nav.waypointSymbol); // can we sell anything here? const goods = whatCanBeTradedAt(cargo.goods, market.imports.concat(market.exchange)); for (let i = 0; i < goods.length; i++) { - await libShips.sell(ship, goods[i].symbol); + await ship.sell(goods[i].symbol); }; // are we done selling everything we can? - ship = dbShips.getShip(ship.symbol); - cargo = utils.categorizeCargo(ship.cargo, good); + cargo = categorizeCargo(ship.cargo, good); if (Object.keys(cargo.goods).length === 0) { return ship; } @@ -50,7 +47,7 @@ export async function sell(ship: Ship, good: string): Promise<Ship> { // if we have no data on the market we need to go there and see // and if we have data and can sell there we need to go too if (market === null || whatCanBeTradedAt(cargo.goods, market.imports).length > 0) { - await libShips.navigate(ship, waypointSymbol); + await ship.navigate(waypointSymbol); continue outer; } } @@ -60,7 +57,7 @@ export async function sell(ship: Ship, good: string): Promise<Ship> { const market = await libSystems.market(waypointSymbol); // if we can sell there we need to go if (whatCanBeTradedAt(cargo.goods, market.exchange).length > 0) { - await libShips.navigate(ship, waypointSymbol); + await ship.navigate(waypointSymbol); continue outer; } } diff --git a/nodejs/database/agents.ts b/nodejs/database/agents.ts index 3fc4182..5221dc7 100644 --- a/nodejs/database/agents.ts +++ b/nodejs/database/agents.ts @@ -1,4 +1,4 @@ -import { Agent } from '../model/agent.ts'; +import { Agent } from '../lib/types.ts'; import { DbData, db } from './db.ts'; const addAgentStatement = db.prepare(`INSERT INTO agents(data) VALUES (json(?));`); diff --git a/nodejs/database/contracts.ts b/nodejs/database/contracts.ts index 64d6c65..9adb4c8 100644 --- a/nodejs/database/contracts.ts +++ b/nodejs/database/contracts.ts @@ -1,4 +1,4 @@ -import { Contract } from '../model/contract.ts'; +import { Contract } from '../lib/types.ts'; import { DbData, db } from './db.ts'; const addContractStatement = db.prepare(`INSERT INTO contracts(data) VALUES (json(?));`); diff --git a/nodejs/database/markets.ts b/nodejs/database/markets.ts index 558d181..6e8865a 100644 --- a/nodejs/database/markets.ts +++ b/nodejs/database/markets.ts @@ -1,5 +1,5 @@ import { DbData, db } from './db.ts'; -import { Market } from '../model/market.ts'; +import { Market } from '../lib/types.ts'; import { systemFromWaypoint } from '../lib/utils.ts'; const addMarketStatement = db.prepare(`INSERT INTO markets(system, data) VALUES (?, json(?));`); diff --git a/nodejs/database/ships.ts b/nodejs/database/ships.ts deleted file mode 100644 index c827db8..0000000 --- a/nodejs/database/ships.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { DbData, db } from './db.ts'; -import { Cargo } from '../model/cargo.ts'; -import { Fuel, Nav, Ship } from '../model/ship.ts'; - -const addShipStatement = db.prepare(`INSERT INTO ships(data) VALUES (json(?));`); -const getShipStatement = db.prepare(`SELECT data FROM ships WHERE data->>'symbol' = ?;`); -const getShipsAtStatement = db.prepare(`SELECT data FROM ships WHERE data->>'$.nav.systemSymbol' = ?;`); -const getShipsStatement = db.prepare(`SELECT data FROM ships;`); -const setShipCargoStatement = db.prepare(`UPDATE ships SET data = (SELECT json_set(data, '$.cargo', json(:cargo)) FROM ships WHERE data->>'symbol' = :symbol) WHERE data->>'symbol' = :symbol;`); -const setShipFuelStatement = db.prepare(`UPDATE ships SET data = (SELECT json_set(data, '$.fuel', json(:fuel)) FROM ships WHERE data->>'symbol' = :symbol) WHERE data->>'symbol' = :symbol;`); -const setShipNavStatement = db.prepare(`UPDATE ships SET data = (SELECT json_set(data, '$.nav', json(:nav)) FROM ships WHERE data->>'symbol' = :symbol) WHERE data->>'symbol' = :symbol;`); -const updateShipStatement = db.prepare(`UPDATE ships SET data = json(:data) WHERE data->>'symbol' = :symbol;`); - -export function getShip(symbol: string): Ship { - const data = getShipStatement.get(symbol) as DbData|undefined; - if (!data) throw `invalid symbol ${symbol} in getShip database call`; - return JSON.parse(data.data); -} - -export function getShips(): Array<Ship> { - const data = getShipsStatement.all() as Array<DbData>; - return data.map(elt => JSON.parse(elt.data)); -} - -export function getShipsAt(symbol: string): Array<Ship> { - const data = getShipsAtStatement.all(symbol) as Array<DbData>; - return data.map(elt => JSON.parse(elt.data)); -} - -export function setShip(data: Ship): void { - const changes = updateShipStatement.run({ - data: JSON.stringify(data), - symbol: data.symbol, - }).changes; - if (changes === 0) addShipStatement.run(JSON.stringify(data)); -} - -export function setShipCargo(symbol: string, cargo: Cargo): void { - setShipCargoStatement.run({ - cargo: JSON.stringify(cargo), - symbol: symbol, - }); -} - -export function setShipFuel(symbol: string, fuel: Fuel): void { - setShipFuelStatement.run({ - fuel: JSON.stringify(fuel), - symbol: symbol, - }); -} - -export function setShipNav(symbol: string, nav: Nav): void { - setShipNavStatement.run({ - nav: JSON.stringify(nav), - symbol: symbol, - }); -} diff --git a/nodejs/database/systems.ts b/nodejs/database/systems.ts index d6d6cf1..646222e 100644 --- a/nodejs/database/systems.ts +++ b/nodejs/database/systems.ts @@ -1,5 +1,5 @@ import { DbData, db } from './db.ts'; -import { System, Waypoint } from '../model/system.ts'; +import { System, Waypoint } from '../lib/types.ts'; const addSystemStatement = db.prepare(`INSERT INTO systems(data) VALUES (json(?));`); const getSystemStatement = db.prepare(`SELECT data FROM systems WHERE data->>'symbol' = ?;`); diff --git a/nodejs/lib/api.ts b/nodejs/lib/api.ts index f023ccf..2bb81a6 100644 --- a/nodejs/lib/api.ts +++ b/nodejs/lib/api.ts @@ -3,8 +3,39 @@ import events from 'events'; import { PriorityQueue } from './priority_queue.ts'; import { getToken } from '../database/tokens.ts'; -import { APIError, Request, RequestPromise, Response } from '../model/api.ts'; -import { RateLimitError } from '../model/errors.ts'; +import { RateLimitError } from './errors.ts'; + +export type APIError = { + error: string; + code: number; + data: unknown; +}; + +export type Meta = { + limit: number; + page: number; + total: number; +} + +export type Request = { + endpoint: string; // the path part of the url to call + method?: string; // HTTP method for `fetch` call, defaults to 'GET' + page?: number; // run a paginated request starting from this page until all the following pages are fetched + payload?: { [key:string]: any}; // optional json object that will be sent along the request + priority?: number; // optional priority value, defaults to 10. lower than 10 means the message will be sent faster +}; + +export type RequestPromise<T> = { + reject: (reason?: any) => void; + request: Request; + resolve: (value: Response<T> | PromiseLike<Response<T>>) => void; +}; + +export type Response<T> = { + data: T; + error?: APIError; + meta?: Meta; +} // queue processor module variables const bus = new events.EventEmitter(); // a bus to notify the queue processor to start processing messages diff --git a/nodejs/lib/contracts.ts b/nodejs/lib/contracts.ts index 2b6f877..833d434 100644 --- a/nodejs/lib/contracts.ts +++ b/nodejs/lib/contracts.ts @@ -1,20 +1,24 @@ -import { Agent } from '../model/agent.ts'; -import { APIError } from '../model/api.ts'; -import { Cargo } from '../model/cargo.ts'; -import { Contract } from '../model/contract.ts'; -import { Ship } from '../model/ship.ts'; +import { + Agent, + Cargo, + Contract, +} from './types.ts'; +import { + APIError, + debugLog, + send, + sendPaginated, +} from './api.ts'; +import { Ship } from './ships.ts'; import * as dbAgents from '../database/agents.ts'; import * as dbContracts from '../database/contracts.ts'; -import * as api from './api.ts'; -import * as dbShips from '../database/ships.ts'; -import * as libShips from '../lib/ships.ts'; export async function accept(contract: Contract): Promise<Contract> { contract = dbContracts.getContract(contract.id); if (contract.accepted) return contract; - const response = await api.send<{agent: Agent, contract: Contract, type: ''}>({endpoint: `/my/contracts/${contract.id}/accept`, method: 'POST'}); + const response = await send<{agent: Agent, contract: Contract, type: ''}>({endpoint: `/my/contracts/${contract.id}/accept`, method: 'POST'}); if (response.error) { - api.debugLog(response); + debugLog(response); throw response; } dbAgents.setAgent(response.data.agent); @@ -23,7 +27,7 @@ export async function accept(contract: Contract): Promise<Contract> { } export async function getContracts(): Promise<Array<Contract>> { - const response = await api.sendPaginated<Contract>({endpoint: '/my/contracts'}); + const response = await sendPaginated<Contract>({endpoint: '/my/contracts'}); response.forEach(contract => dbContracts.setContract(contract)); return response; } @@ -32,9 +36,9 @@ export async function getContract(contract: Contract): Promise<Contract> { try { return dbContracts.getContract(contract.id); } catch {} - const response = await api.send<Contract>({endpoint: `/my/contracts/${contract.id}`}); + const response = await send<Contract>({endpoint: `/my/contracts/${contract.id}`}); if (response.error) { - api.debugLog(response); + debugLog(response); throw response; } dbContracts.setContract(response.data); @@ -43,15 +47,14 @@ export async function getContract(contract: Contract): Promise<Contract> { export async function deliver(contract: Contract, ship: Ship): Promise<Contract> { contract = dbContracts.getContract(contract.id); - ship = dbShips.getShip(ship.symbol); if (contract.terms.deliver[0].unitsRequired <= contract.terms.deliver[0].unitsFulfilled) { return await fulfill(contract); } const tradeSymbol = contract.terms.deliver[0].tradeSymbol; let units = 0; ship.cargo.inventory.forEach(i => {if (i.symbol === tradeSymbol) units = i.units; }); - await libShips.dock(ship); // we need to be docked to deliver - const response = await api.send<{contract: Contract, cargo: Cargo}>({ endpoint: `/my/contracts/${contract.id}/deliver`, method: 'POST', payload: { + await ship.dock(); // we need to be docked to deliver + const response = await send<{contract: Contract, cargo: Cargo}>({ endpoint: `/my/contracts/${contract.id}/deliver`, method: 'POST', payload: { shipSymbol: ship.symbol, tradeSymbol: tradeSymbol, units: units, @@ -61,12 +64,12 @@ export async function deliver(contract: Contract, ship: Ship): Promise<Contract> case 4509: // contract delivery terms have been met return await fulfill(contract); default: // yet unhandled error - api.debugLog(response); + debugLog(response); throw response; } } dbContracts.setContract(response.data.contract); - dbShips.setShipCargo(ship.symbol, response.data.cargo); + ship.cargo = response.data.cargo; if(response.data.contract.terms.deliver[0].unitsRequired <= response.data.contract.terms.deliver[0].unitsFulfilled) { return await fulfill(response.data.contract); } @@ -76,9 +79,9 @@ export async function deliver(contract: Contract, ship: Ship): Promise<Contract> export async function fulfill(contract: Contract): Promise<Contract> { contract = dbContracts.getContract(contract.id); if (contract.fulfilled) return contract; - const response = await api.send<{agent: Agent, contract: Contract}>({ endpoint: `/my/contracts/${contract.id}/fulfill`, method: 'POST'}); + const response = await send<{agent: Agent, contract: Contract}>({ endpoint: `/my/contracts/${contract.id}/fulfill`, method: 'POST'}); if (response.error) { - api.debugLog(response); + debugLog(response); throw response; } dbAgents.setAgent(response.data.agent); diff --git a/nodejs/lib/errors.ts b/nodejs/lib/errors.ts new file mode 100644 index 0000000..f9dca89 --- /dev/null +++ b/nodejs/lib/errors.ts @@ -0,0 +1,35 @@ +import { Cooldown } from './types.ts'; + +export type MarketTradeVolumeError = { + waypointSymbol: string; + tradeSymbol: string; + units: number; + tradeVolume: number; +}; + +export type RateLimitError = { + type: string; + retryAfter: number; + limitBurst: number; + limitPerSecond: number; + remaining: number; + reset: Date; +}; + +export type ShipIsCurrentlyInTransitError = { + arrival: Date; + departureSymbol: string; + departureTime: Date; + destinationSymbol: string; + secondsToArrival: number; +}; + +export type ShipIsStillOnCooldownError = { + cooldown: Cooldown; +}; + +export type ShipRequiresMoreFuelForNavigationError = { + fuelAvailable: number; + fuelRequired: number; + shipSymbol: string; +}; diff --git a/nodejs/lib/ships.ts b/nodejs/lib/ships.ts index 83b2e86..7221596 100644 --- a/nodejs/lib/ships.ts +++ b/nodejs/lib/ships.ts @@ -1,240 +1,207 @@ -import { Response } from '../model/api.ts'; -import { Agent } from '../model/agent.ts'; -import { Cargo } from '../model/cargo.ts'; -import { Contract } from '../model/contract.ts'; -import { Cooldown, Fuel, Nav, Ship } from '../model/ship.ts'; -import * as api from './api.ts'; +import { + Response, + debugLog, + send, + sleep, +} from './api.ts'; +import { + MarketTradeVolumeError, + ShipIsCurrentlyInTransitError, + ShipIsStillOnCooldownError, + ShipRequiresMoreFuelForNavigationError, +} from './errors.ts'; +import { + Agent, + Cargo, + Contract, + Cooldown, + Fuel, + Nav, + Registration, +} from './types.ts'; import * as dbAgents from '../database/agents.ts'; -import * as dbShips from '../database/ships.ts'; -//import * as dbSurveys from '../database/surveys.ts'; -import * as systems from '../lib/systems.ts'; -export async function buy(ship: Ship, tradeSymbol: string, units: number): Promise<void> { - if (units <= 0) return; - ship = await getShip(ship); - await dock(ship); - // TODO take into account the tradevolume, we might need to buy in multiple steps - const response = await api.send<{agent: Agent, cargo: Cargo}>({endpoint: `/my/ships/${ship.symbol}/purchase`, method: 'POST', payload: { symbol: tradeSymbol, units: units }}); // TODO transaction field +export async function getShips(): Promise<Array<Ship>> { + const response = await send<Array<Ship>>({endpoint: `/my/ships`, page: 1}); if (response.error) { - api.debugLog(response); + debugLog(response); throw response; } - dbShips.setShipCargo(ship.symbol, response.data.cargo); - dbAgents.setAgent(response.data.agent); + return response.data.map(ship => new Ship(ship)); } -export async function dock(ship: Ship): Promise<void> { - ship = await getShip(ship); - if (ship.nav.status === 'DOCKED') return; - const response = await api.send<{nav: Nav}>({endpoint: `/my/ships/${ship.symbol}/dock`, method: 'POST'}); - if (response.error) { - switch(response.error.code) { - case 4214: // ship is in transit - const errorData = response.error.data as { secondsToArrival: number}; - await api.sleep(errorData.secondsToArrival * 1000); - return await dock(ship); - default: // yet unhandled error - api.debugLog(response); - throw response; - } +export class Ship { + cargo: Cargo; + cooldown: Cooldown; + // crew + // engine + // frame + fuel: Fuel; + // modules + // mounts + nav: Nav; + // reactor + registration: Registration; + symbol: string; + constructor(ship: Ship) { + this.cargo = ship.cargo; + this.cooldown = ship.cooldown; + this.fuel = ship.fuel; + this.nav = ship.nav; + this.registration = ship.registration; + this.symbol = ship.symbol; } - dbShips.setShipNav(ship.symbol, response.data.nav); -} - -export async function extract(ship: Ship): Promise<Cargo> { - ship = await getShip(ship); - if (await isFull(ship)) return ship.cargo; - // TODO move to a suitable asteroid? - // const asteroidFields = await systems.type({symbol: ship.nav.systemSymbol, type: 'ENGINEERED_ASTEROID'}); - // TODO if there are multiple fields, find the closest one? - //await navigate({symbol: ctx.symbol, waypoint: asteroidFields[0].symbol}); - await orbit(ship); - // TODO handle surveying? - const response = await api.send<{cooldown: Cooldown, cargo: Cargo}>({endpoint: `/my/ships/${ship.symbol}/extract`, method: 'POST'}); // TODO extraction and events api response fields cf https://spacetraders.stoplight.io/docs/spacetraders/b3931d097608d-extract-resources - if (response.error) { - switch(response.error.code) { - case 4000: // ship is on cooldown - const errorData = response.error.data as {cooldown: Cooldown}; - await api.sleep(errorData.cooldown.remainingSeconds * 1000); - return await extract(ship); - case 4228: // ship is full - return ship.cargo; - default: // yet unhandled error - api.debugLog(response); - throw response; + async dock(): Promise<void> { + if (this.nav.status === 'DOCKED') return; + const response = await send<{nav: Nav}>({endpoint: `/my/ships/${this.symbol}/dock`, method: 'POST'}); + if (response.error) { + switch(response.error.code) { + case 4214: + const sicite = response.error.data as ShipIsCurrentlyInTransitError; + await sleep(sicite.secondsToArrival * 1000); + return await this.dock(); + default: // yet unhandled error + debugLog(response); + throw response; + } } - } else { - dbShips.setShipCargo(ship.symbol, response.data.cargo); - await api.sleep(response.data.cooldown.remainingSeconds*1000); + this.nav = response.data.nav; } - return response.data.cargo -} - -export async function isFull(ship: Ship): Promise<boolean> { - ship = await getShip(ship); - return ship.cargo.units >= ship.cargo.capacity * 0.9; -} - -//function hasMount(shipSymbol, mountSymbol) { -// const ship = dbShips.getShip(shipSymbol); -// return ship.mounts.filter(s => s.symbol === mountSymbol).length > 0; -//} - -//export async function jump(ship: Ship): Ship { -// // TODO -// const response = await api.send({endpoint: `/my/ships/${ctx.ship}/jump`, method: 'POST', payload: { systemSymbol: ctx.system }}); -// await api.sleep(response.data.cooldown.remainingSeconds*1000); -// return response; -//} - -export async function navigate(ship: Ship, waypoint: string): Promise<void> { - ship = await getShip(ship); - if (ship.nav.waypointSymbol === waypoint) return; - await orbit(ship); - // TODO if we do not have enough fuel, make a stop to refuel along the way or drift to the destination - const response = await api.send<{fuel: Fuel, nav: Nav}>({endpoint: `/my/ships/${ship.symbol}/navigate`, method: 'POST', payload: { waypointSymbol: waypoint }}); // TODO events field - if (response.error) { - switch(response.error.code) { - case 4214: // ship is in transit - const errorData = response.error.data as { secondsToArrival: number}; - await api.sleep(errorData.secondsToArrival * 1000); - return await navigate(ship, waypoint); - default: // yet unhandled error - api.debugLog(response); - throw response; + async extract(): Promise<Cargo> { + if (this.isFull()) return this.cargo; + // TODO move to a suitable asteroid? + // const asteroidFields = await systems.type({symbol: this.nav.systemSymbol, type: 'ENGINEERED_ASTEROID'}); + // TODO if there are multiple fields, find the closest one? + //await navigate({symbol: ctx.symbol, waypoint: asteroidFields[0].symbol}); + await this.orbit(); + // TODO handle surveying? + const response = await send<{cooldown: Cooldown, cargo: Cargo}>({endpoint: `/my/ships/${this.symbol}/extract`, method: 'POST'}); // TODO extraction and events api response fields cf https://spacetraders.stoplight.io/docs/spacetraders/b3931d097608d-extract-resources + if (response.error) { + switch(response.error.code) { + case 4000: + const sisoce = response.error.data as ShipIsStillOnCooldownError; + await sleep(sisoce.cooldown.remainingSeconds * 1000); + return await this.extract(); + case 4228: // ship is full + return this.cargo; + default: // yet unhandled error + debugLog(response); + throw response; + } } + this.cargo = response.data.cargo; + await sleep(response.data.cooldown.remainingSeconds*1000); + return this.cargo; } - dbShips.setShipFuel(ship.symbol, response.data.fuel); - dbShips.setShipNav(ship.symbol, response.data.nav); - const delay = new Date(response.data.nav.route.arrival).getTime() - new Date().getTime() ; - await api.sleep(delay); - response.data.nav.status = 'IN_ORBIT'; // we arrive in orbit - dbShips.setShipNav(ship.symbol, response.data.nav); - // TODO only refuel at the start of a journey, if we do not have enough OR if the destination does not sell fuel? - await refuel(ship); -} - -export async function negotiate(ship: Ship): Promise<Contract> { - ship = await getShip(ship); - const response = await api.send<{contract: Contract}>({endpoint: `/my/ships/${ship.symbol}/negotiate/contract`, method: 'POST'}); - if (response.error) { - switch(response.error.code) { - case 4214: // ship is in transit - const errorData = response.error.data as { secondsToArrival: number}; - await api.sleep(errorData.secondsToArrival * 1000); - return await negotiate(ship); - default: // yet unhandled error - api.debugLog(response); - throw response; + isFull(): boolean { + return this.cargo.units >= this.cargo.capacity * 0.9; + } + async navigate(waypointSymbol: string): Promise<void> { + if (this.nav.waypointSymbol === waypointSymbol) return; + const d = + // TODO compute fuel consumption and refuel if we do not have enough OR if the destination does not sell fuel? + await this.refuel(); + await this.orbit(); + // TODO if we do not have enough fuel, make a stop to refuel along the way or drift to the destination + const response = await send<{fuel: Fuel, nav: Nav}>({endpoint: `/my/ships/${this.symbol}/navigate`, method: 'POST', payload: { waypointSymbol: waypointSymbol }}); // TODO events field + if (response.error) { + switch(response.error.code) { + case 4203: // not enough fuel + const srmffne = response.error.data as ShipRequiresMoreFuelForNavigationError; + // TODO test if it exceeds our maximum + // find an intermediate stop to refuel if that is the case + debugLog(response); + throw response; + //await refuel(ship); + //return await navigate(ship, waypoint); + case 4214: + const sicite = response.error.data as ShipIsCurrentlyInTransitError; + await sleep(sicite.secondsToArrival * 1000); + return await this.navigate(waypointSymbol); + default: // yet unhandled error + debugLog(response); + throw response; + } } + this.fuel = response.data.fuel; + this.nav = response.data.nav; + const delay = new Date(this.nav.route.arrival).getTime() - new Date().getTime() ; + await sleep(delay); + this.nav.status = 'IN_ORBIT'; // we arrive in orbit } - return response.data.contract; -} - -export async function orbit(ship: Ship): Promise<void> { - ship = await getShip(ship); - if (ship.nav.status === 'IN_ORBIT') return; - const response = await api.send<{nav: Nav}>({endpoint: `/my/ships/${ship.symbol}/orbit`, method: 'POST'}); - if (response.error) { - switch(response.error.code) { - case 4214: // ship is in transit - const errorData = response.error.data as { secondsToArrival: number}; - await api.sleep(errorData.secondsToArrival * 1000); - return await orbit(ship); - default: // yet unhandled error - api.debugLog(response); - throw response; + async negotiate(): Promise<Contract> { + const response = await send<{contract: Contract}>({endpoint: `/my/ships/${this.symbol}/negotiate/contract`, method: 'POST'}); + if (response.error) { + switch(response.error.code) { + case 4214: + const sicite = response.error.data as ShipIsCurrentlyInTransitError; + await sleep(sicite.secondsToArrival * 1000); + return await this.negotiate(); + default: // yet unhandled error + debugLog(response); + throw response; + } } + return response.data.contract; } - dbShips.setShipNav(ship.symbol, response.data.nav); -} - -//export async function purchase(ctx) { -// const response = await api.send({endpoint: '/my/ships', method: 'POST', payload: { -// shipType: ctx.shipType, -// waypointSymbol: ctx.waypoint, -// }}); -// if (response.error !== undefined) { -// throw response; -// } -// dbShips.setShip(response.data.ship); -// return response.data; -//} - -export async function refuel(ship: Ship): Promise<void> { - ship = await getShip(ship); - if (ship.fuel.current >= ship.fuel.capacity * 0.9) return; - // TODO check if our current waypoint has a marketplace (and sells fuel)? - await dock(ship); - const response = await api.send<{agent: Agent, fuel: Fuel}>({endpoint: `/my/ships/${ship.symbol}/refuel`, method: 'POST'}); // TODO transaction field - if (response.error) { - api.debugLog(response); - throw response; + async orbit(): Promise<void> { + if (this.nav.status === 'IN_ORBIT') return; + const response = await send<{nav: Nav}>({endpoint: `/my/ships/${this.symbol}/orbit`, method: 'POST'}); + if (response.error) { + switch(response.error.code) { + case 4214: + const sicite = response.error.data as ShipIsCurrentlyInTransitError; + await sleep(sicite.secondsToArrival * 1000); + return await this.orbit(); + default: // yet unhandled error + debugLog(response); + throw response; + } + } + this.nav = response.data.nav; } - dbShips.setShipFuel(ship.symbol, response.data.fuel); - dbAgents.setAgent(response.data.agent); -} - -export async function sell(ship: Ship, tradeSymbol: string): Promise<Cargo> { - ship = await getShip(ship); - // TODO check if our current waypoint has a marketplace and buys tradeSymbol? - await dock(ship); - let units = 0; - ship.cargo.inventory.forEach(i => {if (i.symbol === tradeSymbol) units = i.units; }); - const response = await api.send<{agent: Agent, cargo: Cargo}>({endpoint: `/my/ships/${ship.symbol}/sell`, method: 'POST', payload: { symbol: tradeSymbol, units: units }}); // TODO transaction field - if (response.error) { - api.debugLog(response); - throw response; + async purchase(tradeSymbol: string, units: number): Promise<void> { + if (units <= 0) return; + await this.dock(); + // TODO take into account the tradevolume, we might need to buy in multiple steps + const response = await send<{agent: Agent, cargo: Cargo}>({endpoint: `/my/ships/${this.symbol}/purchase`, method: 'POST', payload: { symbol: tradeSymbol, units: units }}); // TODO transaction field + if (response.error) { + switch(response.error.code) { + case 4604: // units per transaction limit exceeded + const mtve = response.error.data as MarketTradeVolumeError; + await this.purchase(tradeSymbol, mtve.tradeVolume); + return await this.purchase(tradeSymbol, units - mtve.tradeVolume); + default: + debugLog(response); + throw response; + } + } + this.cargo = response.data.cargo; + dbAgents.setAgent(response.data.agent); } - dbShips.setShipCargo(ship.symbol, response.data.cargo); - dbAgents.setAgent(response.data.agent); - return response.data.cargo; -} - -export async function getShips(): Promise<Array<Ship>> { - const response = await api.send<Array<Ship>>({endpoint: `/my/ships`, page: 1}); - if (response.error) { - api.debugLog(response); - throw response; + async refuel(): Promise<void> { + // TODO check if our current waypoint has a marketplace (and sells fuel)? + await this.dock(); + const response = await send<{agent: Agent, fuel: Fuel}>({endpoint: `/my/ships/${this.symbol}/refuel`, method: 'POST'}); // TODO transaction field + if (response.error) { + debugLog(response); + throw response; + } + this.fuel = response.data.fuel; + dbAgents.setAgent(response.data.agent); } - response.data.forEach(ship => dbShips.setShip(ship)); - return response.data; -} - -export async function getShip(ship: Ship): Promise<Ship> { - try { - return dbShips.getShip(ship.symbol); - } catch {} - const response = await api.send<Ship>({endpoint: `/my/ships/${ship.symbol}`}); - if (response.error) { - api.debugLog(response); - throw response; + async sell(tradeSymbol: string): Promise<Cargo> { + // TODO check if our current waypoint has a marketplace and buys tradeSymbol? + await this.dock(); + let units = 0; + this.cargo.inventory.forEach(i => {if (i.symbol === tradeSymbol) units = i.units; }); + const response = await send<{agent: Agent, cargo: Cargo}>({endpoint: `/my/ships/${this.symbol}/sell`, method: 'POST', payload: { symbol: tradeSymbol, units: units }}); // TODO transaction field + if (response.error) { + debugLog(response); + throw response; + } + this.cargo = response.data.cargo; + dbAgents.setAgent(response.data.agent); + return this.cargo; } - dbShips.setShip(response.data); - return response.data; } - -//export async function survey(ctx) { -// if (!hasMount(ctx.symbol, 'MOUNT_SURVEYOR_I')) { // we check if a surveyor is mounted on the ship -// return null; -// } -// const ship = dbShips.getShip(ctx.symbol); -// const asteroidFields = await systems.type({symbol: ship.nav.systemSymbol, type: 'ASTEROID_FIELD'}); -// // TODO if there are multiple fields, find the closest one? -// await navigate({symbol: ctx.symbol, waypoint: asteroidFields[0].symbol}); -// await orbit(ctx); -// const response = await api.send({endpoint: `/my/ships/${ctx.symbol}/survey`, method: 'POST'}); -// api.debugLog(response); -// if (response.error !== undefined) { -// switch(response.error.code) { -// case 4000: // ship is on cooldown -// await api.sleep(response.error.data.cooldown.remainingSeconds * 1000); -// return await survey(ctx); -// default: // yet unhandled error -// throw response; -// } -// } -// dbSurveys.set(response.data.surveys[0]); -// await api.sleep(response.data.cooldown.remainingSeconds*1000); -// return response; -//} diff --git a/nodejs/lib/systems.ts b/nodejs/lib/systems.ts index dc938bb..97aa6e3 100644 --- a/nodejs/lib/systems.ts +++ b/nodejs/lib/systems.ts @@ -1,18 +1,24 @@ -import * as api from './api.ts'; +import { + debugLog, + send, + sendPaginated, +} from './api.ts'; import * as dbMarkets from '../database/markets.ts'; -import * as dbShips from '../database/ships.ts'; import * as dbSystems from '../database/systems.ts'; -import { Market } from '../model/market.ts' -import { System, Waypoint } from '../model/system.ts' -import * as utils from './utils.ts'; +import { + Market, + System, + Waypoint +} from './types.ts' +import { systemFromWaypoint } from './utils.ts'; export async function market(waypointSymbol: string): Promise<Market> { const data = dbMarkets.getMarketAtWaypoint(waypointSymbol); if (data) { return data; } - const systemSymbol = utils.systemFromWaypoint(waypointSymbol); - let response = await api.send<Market>({endpoint: `/systems/${systemSymbol}/waypoints/${waypointSymbol}/market`}); + const systemSymbol = systemFromWaypoint(waypointSymbol); + let response = await send<Market>({endpoint: `/systems/${systemSymbol}/waypoints/${waypointSymbol}/market`}); if (response.error) { - api.debugLog(response); + debugLog(response); throw response; } dbMarkets.setMarket(response.data); @@ -21,16 +27,16 @@ export async function market(waypointSymbol: string): Promise<Market> { //export async function shipyard(waypoint: string): Promise<unknown> { // // TODO database caching -// const systemSymbol = utils.systemFromWaypoint(waypoint); -// return await api.send({endpoint: `/systems/${systemSymbol}/waypoints/${waypoint}/shipyard`}); +// const systemSymbol = systemFromWaypoint(waypoint); +// return await send({endpoint: `/systems/${systemSymbol}/waypoints/${waypoint}/shipyard`}); //} export async function system(symbol: string): Promise<System> { let data = dbSystems.getSystem(symbol); if (data) { return data; } - const response = await api.send<System>({endpoint: `/systems/${symbol}`}); + const response = await send<System>({endpoint: `/systems/${symbol}`}); if (response.error) { - api.debugLog(response); + debugLog(response); throw response; } dbSystems.setSystem(response.data); @@ -54,7 +60,7 @@ export async function waypoints(systemSymbol: string): Promise<Array<Waypoint>> const updated = dbSystems.getSystemUpdated(systemSymbol); // TODO handle uncharted systems if (updated) return s.waypoints; - const waypoints = await api.sendPaginated<Waypoint>({endpoint: `/systems/${systemSymbol}/waypoints`}); + const waypoints = await sendPaginated<Waypoint>({endpoint: `/systems/${systemSymbol}/waypoints`}); dbSystems.setSystemWaypoints(systemSymbol, waypoints); return waypoints; } diff --git a/nodejs/lib/types.ts b/nodejs/lib/types.ts new file mode 100644 index 0000000..a8e748c --- /dev/null +++ b/nodejs/lib/types.ts @@ -0,0 +1,145 @@ +export type Agent = { + accountId: string; + credits: number; + headquarters: string; + shipCount: number; + startingFaction: string; + symbol: string; +}; + +export type CommonThing = { + description: string; + name: string; + symbol: string; +}; + +export type Cargo = { + capacity: number; + units: number; + inventory: Array<Inventory>; +}; + +// Custom type, not from space traders api +export type CargoManifest = { + [key: string]: number; +}; + +export type Chart = { + waypointSymbol: string; + submittedBy: string; + submittedOn: Date; +}; + +export type Contract = { + id: string; + factionSymbol: string; + type: string; + terms: { + deadline: Date; + payment: { + onAccepted: number; + onFulfilled: number; + }, + deliver: Array<{ + tradeSymbol: string; + destinationSymbol: string; + unitsRequired: number; + unitsFulfilled: number; + }>; + }; + accepted: boolean; + fulfilled: boolean; + expiration: Date; + deadlineToAccept: Date; +}; + +export type Cooldown = { + shipSymbol: string; + totalSeconds: number; + remainingSeconds: number; +}; + +export type Consummed = { + amount: number; + timestamp: Date; +}; + +export type Fuel = { + capacity: number; + consummed: Consummed; + current: number; +}; + +export type Inventory = CommonThing & { + units: number; +}; + +export type Market = { + symbol: string; + exchange: Array<CommonThing>; + exports: Array<CommonThing>; + imports: Array<CommonThing>; + //transactions: Array<Transaction>; + tradeGoods: Array<TradeGood>; +}; + +export type Nav = { + flightMode: string; + route: Route; + status: string; + systemSymbol: string; + waypointSymbol: string; +}; + +export type Registration = { + factionSymbol: string; + name: string; + role: string; +}; + +export type Route = { + arrival: Date; + departureTime: Date; + destination: RouteEndpoint; + origin: RouteEndpoint; +}; + +export type RouteEndpoint = { + type: string; + symbol: string; + systemSymbol: string; + x: number; + y: number; +}; + +export type System = { + symbol: string; + sectorSymbol: string; + type: string; + x: number; + y: number; + waypoints: Array<Waypoint>; +}; + +export type TradeGood = CommonThing & { + activity: string; + purchasePrice: number; + sellPrice: number; + supply: string; + tradeVolume: number; + type: string; +}; + +export type Waypoint = { + chart: Chart; + factions: Array<{symbol: string;}>; + isUnderConstruction: boolean; + modifiers: Array<CommonThing>; + orbitals: Array<{symbol: string;}>; + orbits: string; + symbol: string; + traits: Array<CommonThing>; + type: string; + x: number; + y: number; +}; diff --git a/nodejs/lib/utils.ts b/nodejs/lib/utils.ts index c5093a6..39378e9 100644 --- a/nodejs/lib/utils.ts +++ b/nodejs/lib/utils.ts @@ -1,4 +1,4 @@ -import { Cargo, CargoManifest } from '../model/cargo.ts'; +import { Cargo, CargoManifest } from './types.ts'; export type CategorizedCargo = { wanted: CargoManifest; diff --git a/nodejs/main.ts b/nodejs/main.ts index dfb7d89..2d15c60 100755 --- a/nodejs/main.ts +++ b/nodejs/main.ts @@ -1,10 +1,10 @@ import * as autoContracting from './automation/contracting.ts'; //import * as autoExploring from './automation/exploration.ts'; import * as autoInit from './automation/init.ts'; -//import * as api from './lib/api.ts'; -//import * as contracts from './lib/contracts.ts'; +import { getShips } from './lib/ships.ts'; await autoInit.init(); +const ships = await getShips(); -await autoContracting.init(); +await autoContracting.run(ships[0]); // dedicate the command ship to running contracts //autoExploring.init(); diff --git a/nodejs/model/agent.ts b/nodejs/model/agent.ts deleted file mode 100644 index dce6424..0000000 --- a/nodejs/model/agent.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type Agent = { - accountId: string; - credits: number; - headquarters: string; - shipCount: number; - startingFaction: string; - symbol: string; -}; diff --git a/nodejs/model/api.ts b/nodejs/model/api.ts deleted file mode 100644 index 69c7ee1..0000000 --- a/nodejs/model/api.ts +++ /dev/null @@ -1,31 +0,0 @@ -export type APIError = { - error: string; - code: number; - data: unknown; -}; - -export type Meta = { - limit: number; - page: number; - total: number; -} - -export type Request = { - endpoint: string; // the path part of the url to call - method?: string; // HTTP method for `fetch` call, defaults to 'GET' - page?: number; // run a paginated request starting from this page until all the following pages are fetched - payload?: { [key:string]: any}; // optional json object that will be sent along the request - priority?: number; // optional priority value, defaults to 10. lower than 10 means the message will be sent faster -}; - -export type RequestPromise<T> = { - reject: (reason?: any) => void; - request: Request; - resolve: (value: Response<T> | PromiseLike<Response<T>>) => void; -}; - -export type Response<T> = { - data: T; - error?: APIError; - meta?: Meta; -} diff --git a/nodejs/model/cargo.ts b/nodejs/model/cargo.ts deleted file mode 100644 index 869fa49..0000000 --- a/nodejs/model/cargo.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type Inventory = { - description: string; - name: string; - symbol: string; - units: number; -}; - -export type Cargo = { - "capacity": number; - "units": number; - "inventory": Array<Inventory>; -}; - -// Custom type, not from space traders api -export type CargoManifest = { - [key: string]: number; -}; diff --git a/nodejs/model/common.ts b/nodejs/model/common.ts deleted file mode 100644 index 1712ad8..0000000 --- a/nodejs/model/common.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type CommonThing = { - description: string; - name: string; - symbol: string; -}; diff --git a/nodejs/model/contract.ts b/nodejs/model/contract.ts deleted file mode 100644 index eb7add4..0000000 --- a/nodejs/model/contract.ts +++ /dev/null @@ -1,22 +0,0 @@ -export type Contract = { - id: string; - factionSymbol: string; - type: string; - terms: { - deadline: Date; - payment: { - onAccepted: number; - onFulfilled: number; - }, - deliver: Array<{ - tradeSymbol: string; - destinationSymbol: string; - unitsRequired: number; - unitsFulfilled: number; - }>; - }; - accepted: boolean; - fulfilled: boolean; - expiration: Date; - deadlineToAccept: Date; -}; diff --git a/nodejs/model/errors.ts b/nodejs/model/errors.ts deleted file mode 100644 index 6002ae6..0000000 --- a/nodejs/model/errors.ts +++ /dev/null @@ -1,8 +0,0 @@ -export type RateLimitError = { - type: string; - retryAfter: number; - limitBurst: number; - limitPerSecond: number; - remaining: number; - reset: Date; -}; diff --git a/nodejs/model/market.ts b/nodejs/model/market.ts deleted file mode 100644 index 1ba70c1..0000000 --- a/nodejs/model/market.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { CommonThing } from 'common.ts'; - -export type TradeGood = CommonThing & { - activity: string; - purchasePrice: number; - sellPrice: number; - supply: string; - tradeVolume: number; - type: string; -}; - -export type Market = { - symbol: string; - exchange: Array<CommonThing>; - exports: Array<CommonThing>; - imports: Array<CommonThing>; - //transactions: Array<Transaction>; - tradeGoods: Array<TradeGood>; -}; diff --git a/nodejs/model/ship.ts b/nodejs/model/ship.ts deleted file mode 100644 index bf40767..0000000 --- a/nodejs/model/ship.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Cargo } from './cargo.ts'; - -export type Cooldown = { - shipSymbol: string; - totalSeconds: number; - remainingSeconds: number; -}; - -export type Consummed = { - amount: number; - timestamp: Date; -}; - -export type Fuel = { - capacity: number; - consummed: Consummed; - current: number; -}; - -export type Nav = { - flightMode: string; - route: Route; - status: string; - systemSymbol: string; - waypointSymbol: string; -}; - -export type Registration = { - factionSymbol: string; - name: string; - role: string; -}; - -export type Route = { - arrival: Date; - departureTime: Date; - destination: RouteEndpoint; - origin: RouteEndpoint; -}; - -export type RouteEndpoint = { - type: string; - symbol: string; - systemSymbol: string; - x: number; - y: number; -}; - -export type Ship = { - cargo: Cargo; - cooldown: Cooldown; - // crew - // engine - // frame - fuel: Fuel; - // modules - // mounts - nav: Nav; - // reactor - registration: Registration; - symbol: string; -}; diff --git a/nodejs/model/system.ts b/nodejs/model/system.ts deleted file mode 100644 index b90560f..0000000 --- a/nodejs/model/system.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { CommonThing } from 'common.ts'; - -export type Chart = { - waypointSymbol: string; - submittedBy: string; - submittedOn: Date; -}; - -export type System = { - symbol: string; - sectorSymbol: string; - type: string; - x: number; - y: number; - waypoints: Array<Waypoint>; -}; - -export type Waypoint = { - chart: Chart; - factions: Array<{symbol: string;}>; - isUnderConstruction: boolean; - modifiers: Array<CommonThing>; - orbitals: Array<{symbol: string;}>; - orbits: string; - symbol: string; - traits: Array<CommonThing>; - type: string; - x: number; - y: number; -}; |