From a287897da9448d89733dcbc36044fc6f79ad066b Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 28 Dec 2023 19:49:00 +0100 Subject: [PATCH] implementing api changes since 5 months ago --- nullptr/analyzer.py | 1 + nullptr/api.py | 134 ++++++++++++++++++++++--------------- nullptr/atlas_builder.py | 4 +- nullptr/commander.py | 78 +++++++++++++++------ nullptr/models/atlas.py | 5 ++ nullptr/models/base.py | 9 +-- nullptr/models/jumpgate.py | 14 ++-- nullptr/models/ship.py | 13 ++++ nullptr/models/waypoint.py | 3 + 9 files changed, 174 insertions(+), 87 deletions(-) diff --git a/nullptr/analyzer.py b/nullptr/analyzer.py index 90f3107..184c64f 100644 --- a/nullptr/analyzer.py +++ b/nullptr/analyzer.py @@ -52,6 +52,7 @@ class Analyzer: possibles = sorted(candidates, key=lambda m: m[2]) possibles = possibles[:10] results = [] + print(len(possibles)) for typ,m,d in possibles: system = m.waypoint.system p = self.find_path(origin, system) diff --git a/nullptr/api.py b/nullptr/api.py index 655663b..6aeb63b 100644 --- a/nullptr/api.py +++ b/nullptr/api.py @@ -60,7 +60,8 @@ class Api: else: self.last_error = 0 return result['data'] - + + ######## Account ######### def register(self, faction): callsign = self.agent.symbol data = { @@ -77,6 +78,7 @@ class Api: self.agent.update(data) return self.agent + ######## Atlas ######### def list_systems(self, page=1): data = self.request('get', 'systems', params={'page': page}) #pprint(self.last_meta) @@ -87,6 +89,9 @@ class Api: def list_waypoints(self, system): data = self.request('get', f'systems/{system}/waypoints/') + tp = total_pages(self.last_meta) + for p in range(1, tp): + data += self.request('get', f'systems/{system}/waypoints/', params={'page': p}) # pprint(data) return self.store.update_list(Waypoint, data) @@ -100,10 +105,32 @@ class Api: symbol = str(waypoint) return self.store.update(Jumpgate, data, symbol) + def shipyard(self, wp): + return self.request('get', f'systems/{wp.system}/waypoints/{wp}/shipyard') + + ######## Fleet ######### def list_ships(self): data = self.request('get', 'my/ships') return self.store.update_list(Ship, data) + def refuel(self, ship, from_cargo=False): + fuel_need = ship.fuel_capacity - ship.fuel_current + fuel_avail = ship.get_cargo('FUEL') * 100 + units = fuel_need + if from_cargo: + units = min(units, fuel_avail) + data = {'fromCargo': from_cargo, 'units': units } + data = self.request('post', f'my/ships/{ship}/refuel', data) + if from_cargo: + boxes = ceil(float(units) / 100) + ship.take_cargo('FUEL', boxes) + if 'fuel' in data: + ship.update(data) + if 'agent' in data: + self.agent.update(data['agent']) + return data + + ######## Contract ######### def list_contracts(self): data = self.request('get', 'my/contracts') return self.store.update_list('Contract', data) @@ -113,7 +140,15 @@ class Api: if data is not None and 'contract' in data: contract = self.store.update('Contract', data['contract']) return contract - + + def accept_contract(self, contract): + data = self.request('post', f'my/contracts/{contract.symbol.lower()}/accept') + if 'contract' in data: + contract.update(data['contract']) + if 'agent' in data: + self.agent.update(data['agent']) + return contract + def deliver(self, ship, typ, contract): units = ship.get_cargo(typ) if units == 0: @@ -138,7 +173,8 @@ class Api: if 'agent' in data: self.agent.update(data['agent']) return contract - + + ######## Nav ######### def navigate(self, ship, wp): data = {'waypointSymbol': str(wp)} response = self.request('post', f'my/ships/{ship}/navigate', data) @@ -153,23 +189,52 @@ class Api: data = self.request('post', f'my/ships/{ship}/orbit') ship.update(data) return data + + def flight_mode(self, ship, mode): + data = {'flightMode': mode} + data = self.request('patch', f'my/ships/{ship}/nav', data) + return data - def refuel(self, ship): - data = self.request('post', f'my/ships/{ship}/refuel') - if 'fuel' in data: + def jump(self, ship, waypoint): + if type(waypoint) == Waypoint: + waypoint = waypoint.symbol + data = { + "waypointSymbol": waypoint + } + data = self.request('post', f'my/ships/{ship}/jump', data) + if 'nav' in data: ship.update(data) - if 'agent' in data: - self.agent.update(data['agent']) + return ship + + ######## Extraction ######### + def siphon(self, ship): + data = self.request('post', f'my/ships/{ship}/siphon') + ship.update(data) + return data['siphon'] + + def extract(self, ship, survey=None): + data = {} + url = f'my/ships/{ship}/extract' + if survey is not None: + data['survey'] = survey.api_dict() + url += '/survey' + try: + data = self.request('post', url, data=data) + except ApiError as e: + if e.code in [ 4221, 4224]: + survey.exhausted = True + else: + raise e + ship.update(data) return data - def accept_contract(self, contract): - data = self.request('post', f'my/contracts/{contract.symbol.lower()}/accept') - if 'contract' in data: - contract.update(data['contract']) - if 'agent' in data: - self.agent.update(data['agent']) - return contract + def survey(self, ship): + data = self.request('post', f'my/ships/{ship}/survey') + ship.update(data) + result = self.store.update_list('Survey', mg(data, 'surveys')) + return result + ######## Commerce ######### def sell(self, ship, typ): units = ship.get_cargo(typ) data = { @@ -221,41 +286,4 @@ class Api: self.agent.update(data['agent']) if 'ship' in data: ship = self.store.update('Ship', data['ship']) - return ship - - def jump(self, ship, system): - if type(system) == System: - system = system.symbol - data = { - "systemSymbol": system - } - data = self.request('post', f'my/ships/{ship}/jump', data) - if 'nav' in data: - ship.update(data) - return ship - - def shipyard(self, wp): - return self.request('get', f'systems/{wp.system}/waypoints/{wp}/shipyard') - - def extract(self, ship, survey=None): - data = {} - url = f'my/ships/{ship}/extract' - if survey is not None: - data['survey'] = survey.api_dict() - url += '/survey' - try: - data = self.request('post', url, data=data) - except ApiError as e: - if e.code in [ 4221, 4224]: - survey.exhausted = True - else: - raise e - ship.update(data) - return data - - def survey(self, ship): - data = self.request('post', f'my/ships/{ship}/survey') - ship.update(data) - result = self.store.update_list('Survey', mg(data, 'surveys')) - return result - + return ship \ No newline at end of file diff --git a/nullptr/atlas_builder.py b/nullptr/atlas_builder.py index 8587cba..f5f70bf 100644 --- a/nullptr/atlas_builder.py +++ b/nullptr/atlas_builder.py @@ -63,10 +63,10 @@ class AtlasBuilder: if 'UNCHARTED' in w.traits: continue if 'MARKETPLACE' in w.traits: - # print(f'marketplace at {w}') + print(f'marketplace at {w}') self.sched(self.api.marketplace, w) if w.type == 'JUMP_GATE': - # print(f'jumpgate at {w}') + print(f'jumpgate at {w}') self.sched(self.api.jumps, w) if 'SHIPYARD' in w.traits: # todo diff --git a/nullptr/commander.py b/nullptr/commander.py index 5cf67a3..34bb71f 100644 --- a/nullptr/commander.py +++ b/nullptr/commander.py @@ -68,8 +68,11 @@ class Commander(CommandLine): self.agent = agent api = Api(self.store, agent) self.api = api - faction = input('faction: ') - api.register(faction.upper().strip()) + faction = input('faction or token: ') + if len(faction) > 50: + self.agent.token = faction + else: + api.register(faction.upper().strip()) print('=== agent:') print(agent) print('=== ships') @@ -226,15 +229,32 @@ class Commander(CommandLine): r = self.store.all_members(system, 'Waypoint') for w in r: traits = [] - if 'MARKETPLACE' in w.traits: - traits.append('MARKET') - if 'SHIPYARD' in w.traits: - traits.append('SHIPYARD') if w.type == 'JUMP_GATE': traits.append('JUMP') - if w.type == 'ASTEROID_FIELD': - traits.append('ASTROIDS') - print(w.symbol.split('-')[2], ', '.join(traits)) + if 'SHIPYARD' in w.traits: + traits.append('SHIPYARD') + if 'MARKETPLACE' in w.traits: + traits.append('MARKET') + + + if w.type == 'ASTEROID': + if 'COMMON_METAL_DEPOSITS' in w.traits: + traits.append('METAL') + if 'PRECIOUS_METAL_DEPOSITS' in w.traits: + traits.append('GOLD') + if 'EXPLOSIVE_GASSES' in w.traits: + traits.append('GAS') + if 'MINERAL_DEPOSITS' in w.traits: + traits.append('MINS') + if 'STRIPPED' in w.traits: + traits.append('STRIPPED') + + wname = w.symbol.split('-')[2] + traits = ', '.join(traits) + typ = w.type[0] + if typ not in ['F','J'] and len(traits) == 0: + continue + print(f'{wname:4} {typ} {traits}') def do_wp(self, s=''): self.do_waypoints(s) @@ -242,7 +262,11 @@ class Commander(CommandLine): def do_marketplace(self, waypoint_str): waypoint = self.store.get(Waypoint, waypoint_str.upper()) r = self.api.marketplace(waypoint) - + + def do_atlas(self): + atlas = self.store.get(Atlas, 'ATLAS') + pprint(atlas, 5) + def do_jumps(self, waypoint_str=None): if waypoint_str is None: if not self.has_ship(): return @@ -332,15 +356,32 @@ class Commander(CommandLine): self.api.orbit(self.ship) pprint(self.ship) + def do_siphon(self): + if not self.has_ship(): return + data = self.api.siphon(self.ship) + pprint(data) + def do_negotiate(self): if not self.has_ship(): return r = self.api.negotiate(self.ship) pprint(r) - def do_refuel(self): + def do_token(self): + print(self.agent.token) + + def do_speed(self, speed): + if not self.has_ship(): return + speed = speed.upper() + speeds = ['DRIFT', 'STEALTH','CRUISE','BURN'] + if speed not in speeds: + print('please choose from:', speeds) + self.api.flight_mode(self.ship, speed) + + def do_refuel(self, source='market'): if not self.has_ship(): return - r = self.api.refuel(self.ship) - pprint(self.ship) + from_cargo = source != 'market' + r = self.api.refuel(self.ship, from_cargo=from_cargo) + pprint(r) def do_accept(self, c): contract = self.resolve('Contract', c) @@ -358,6 +399,7 @@ class Commander(CommandLine): def do_cargo(self): if not self.has_ship(): return + print(f'== Cargo {self.ship.cargo_units}/{self.ship.cargo_capacity} ==') for c, units in self.ship.cargo.items(): print(f'{units:4d} {c}') @@ -385,13 +427,11 @@ class Commander(CommandLine): for s in must_get(data, 'ships'): print(s['type'], s['purchasePrice']) - def do_jump(self, system_str): + def do_jump(self, waypoint_str): if not self.has_ship(): return - if '-' not in system_str: - sector = self.ship.location.system.sector.symbol - system_str = f'{sector}-{system_str}' - system = self.resolve('System', system_str) - self.api.jump(self.ship, system) + + w = self.resolve('Waypoint', waypoint_str) + self.api.jump(self.ship, w) pprint(self.ship) def do_purchase(self, ship_type): diff --git a/nullptr/models/atlas.py b/nullptr/models/atlas.py index 5851e7c..dd11a99 100644 --- a/nullptr/models/atlas.py +++ b/nullptr/models/atlas.py @@ -9,3 +9,8 @@ class Atlas(Base): self.total_pages = 0 self.seen_pages = 0 + def f(self, detail=1): + r = super().f(detail) + if detail >2: + r += f' {self.seen_pages}/{self.total_pages}' + return r diff --git a/nullptr/models/base.py b/nullptr/models/base.py index 0564a9e..0f7ba6d 100644 --- a/nullptr/models/base.py +++ b/nullptr/models/base.py @@ -57,15 +57,16 @@ class Base: val = interp(val) setattr(self, attr, val) - def setlst(self, attr, d, name, member, interp=None): + def setlst(self, attr, d, name, member=None, interp=None): val = sg(d, name) if val is not None: lst = [] for x in val: - val = sg(x, member) + if member is not None: + x = sg(x, member) if interp is not None: - val = interp(val) - lst.append(val) + x = interp(x) + lst.append(x) setattr(self, attr, lst) def __setattr__(self, name, value): diff --git a/nullptr/models/jumpgate.py b/nullptr/models/jumpgate.py index 0441699..a7092d3 100644 --- a/nullptr/models/jumpgate.py +++ b/nullptr/models/jumpgate.py @@ -1,19 +1,15 @@ from .base import Base -from .system import System +from .waypoint import Waypoint from dataclasses import field class Jumpgate(Base): def define(self): - self.range: int = 0 - self.faction: str = '' - self.systems: list = [] + self.connections: list = [] self.system = self.get_system() def update(self, d): - getter = self.store.getter(System, create=True) - self.setlst('systems', d, 'connectedSystems', 'symbol', interp=getter) - self.seta('faction', d, 'factionSymbol') - self.seta('range', d, 'jumpRange') + getter = self.store.getter(Waypoint, create=True) + self.setlst('connections', d, 'connections', interp=getter) @classmethod def ext(self): @@ -23,5 +19,5 @@ class Jumpgate(Base): r = self.symbol if detail > 1: r += '\n' - r += '\n'.join([s.symbol for s in self.systems]) + r += '\n'.join([s.symbol for s in self.connections]) return r diff --git a/nullptr/models/ship.py b/nullptr/models/ship.py index 42fac30..6989eac 100644 --- a/nullptr/models/ship.py +++ b/nullptr/models/ship.py @@ -54,13 +54,26 @@ class Ship(Base): if typ not in self.cargo: return 0 return self.cargo[typ] + + def take_cargo(self, typ, amt): + if typ not in self.cargo: + return + if self.cargo[typ] <= amt: + del self.cargo[typ] + else: + self.cargo[typ] -= amt + + self.cargo_units = sum(self.cargo.values()) def load_cargo(self, cargo): result = {} + total = 0 for i in cargo: symbol = must_get(i, 'symbol') units = must_get(i, 'units') result[symbol] = units + total += units + self.cargo_units = total self.cargo = result def deliverable_cargo(self, contract): diff --git a/nullptr/models/waypoint.py b/nullptr/models/waypoint.py index 24f007b..aa8b181 100644 --- a/nullptr/models/waypoint.py +++ b/nullptr/models/waypoint.py @@ -10,14 +10,17 @@ class Waypoint(Base): self.type:str = 'unknown' self.traits:list = [] self.faction:str = '' + self.is_under_construction:bool = False self.system = self.get_system() self.uncharted = True + def update(self, d): self.seta('x', d) self.seta('y', d) self.seta('type', d) self.seta('faction', d, 'faction.symbol') + self.seta('is_under_construction', d, 'isUnderConstruction') self.setlst('traits', d, 'traits', 'symbol') self.uncharted = 'UNCHARTED' in self.traits