From 80badca91221e36b7aece195df1155570ec266d2 Mon Sep 17 00:00:00 2001 From: Richard Bronkhorst Date: Mon, 12 Jun 2023 10:51:01 +0200 Subject: [PATCH] Update main.py, api.py and seven other files --- main.py | 1 + nullptr/api.py | 10 +++++++++- nullptr/command_line.py | 2 +- nullptr/commander.py | 23 ++++++++++++++++------- nullptr/models/base.py | 21 +++++++++++++-------- nullptr/models/jumpgate.py | 20 ++++++++++++++++++++ nullptr/models/marketplace.py | 2 +- nullptr/models/waypoint.py | 3 +-- nullptr/store.py | 23 +++++++++++++++++------ 9 files changed, 79 insertions(+), 26 deletions(-) create mode 100644 nullptr/models/jumpgate.py diff --git a/main.py b/main.py index aa02d37..3e6f647 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,7 @@ def main(args): c.run() # X1-AG74-41076A +# X1-KS52-51429E if __name__ == '__main__': parser = argparse.ArgumentParser() diff --git a/nullptr/api.py b/nullptr/api.py index ac23ebe..238f53b 100644 --- a/nullptr/api.py +++ b/nullptr/api.py @@ -2,6 +2,7 @@ import requests from nullptr.models.system import System from nullptr.models.waypoint import Waypoint from nullptr.models.marketplace import Marketplace +from nullptr.models.jumpgate import Jumpgate from .util import * class ApiError(Exception): @@ -71,6 +72,13 @@ class Api: def marketplace(self, waypoint): system = waypoint.system() - symbol = f'{waypoint}-market' + symbol = str(waypoint) data = self.request('get', f'systems/{system}/waypoints/{waypoint}/market') return self.store.update(Marketplace, symbol, data) + + def jumps(self, waypoint): + data = self.request('get', f'systems/{waypoint.system()}/waypoints/{waypoint}/jump-gate') + symbol = str(waypoint) + return self.store.update(Jumpgate, symbol, data) + + diff --git a/nullptr/command_line.py b/nullptr/command_line.py index 8ef8014..55c4acb 100644 --- a/nullptr/command_line.py +++ b/nullptr/command_line.py @@ -35,7 +35,7 @@ class CommandLine: print(f'command not found; {c}') def handle_error(self, cmd, args, e): - logging.error(e, exc_info=str(type(e))=='ApiErrorp') + logging.error(e, exc_info=str(type(e))!='ApiErrorp') def handle_empty(self): pass diff --git a/nullptr/commander.py b/nullptr/commander.py index e9beb62..f28886b 100644 --- a/nullptr/commander.py +++ b/nullptr/commander.py @@ -44,12 +44,12 @@ class Commander(CommandLine): self.stop_auto = True print('stopping...') - def do_universe(self): + def do_universe(self, page=1): print('universe mode. hit enter to stop') t = Thread(target=self.wait_for_stop) t.daemon = True t.start() - self.all_systems() + self.all_systems(int(page)) print('manual mode') def all_specials(self, waypoints): @@ -60,26 +60,30 @@ class Commander(CommandLine): self.api.marketplace(w) print(f'marketplace at {w}') sleep(0.5) + if w.type == 'JUMP_GATE': + self.api.jumps(w) + print(f'jumpgate at {w}') def all_waypoints(self, systems): for s in systems: if self.stop_auto: break r = self.api.list_waypoints(s) - print(f'system {s}: {len(r)} waypoints') self.all_specials(r) + self.store.flush() sleep(0.5) + - def all_systems(self): + def all_systems(self, start_page): self.stop_auto = False - data = self.api.list_systems(1) + data = self.api.list_systems(start_page) pages = total_pages(self.api.last_meta) print(f'{pages} pages of systems') print(f'page {1}: {len(data)} results') self.all_waypoints(data) + self.store.flush() - - for p in range(2, pages): + for p in range(start_page+1, pages): if self.stop_auto: break data = self.api.list_systems(p) @@ -100,4 +104,9 @@ class Commander(CommandLine): def do_marketplace(self, waypoint_str): waypoint = self.store.get(Waypoint, waypoint_str.upper()) r = self.api.marketplace(waypoint) + + def do_jumps(self, waypoint_str): + waypoint = self.store.get(Waypoint, waypoint_str.upper()) + r = self.api.jumps(waypoint) + pprint(r) diff --git a/nullptr/models/base.py b/nullptr/models/base.py index 8b315ef..10c8641 100644 --- a/nullptr/models/base.py +++ b/nullptr/models/base.py @@ -1,16 +1,19 @@ from copy import deepcopy from dataclasses import dataclass from nullptr.util import sg + @dataclass class Base: symbol: str - dirty: bool + store: object def __init__(self, symbol, store): - self.symbol = symbol self.store = store - self.dirty = True + self.symbol = symbol + def __hash__(self): + return hash(self.symbol) + def seta(self, attr, d, name=None): if name is None: name = attr @@ -25,17 +28,19 @@ class Base: setattr(self, attr, lst) def __setattr__(self, name, value): - if name != 'dirty': - self.dirty = True + if name not in ['symbol','store']: + self.store.dirty(self) super().__setattr__(name, value) def update(self, d): pass def dict(self): - r = deepcopy(self.__dict__) - del r['store'] - del r['dirty'] + r = {} + for k,v in self.__dict__.items(): + if k == 'store': + continue + r[k] = deepcopy(v) return r def path(self): diff --git a/nullptr/models/jumpgate.py b/nullptr/models/jumpgate.py new file mode 100644 index 0000000..33da32e --- /dev/null +++ b/nullptr/models/jumpgate.py @@ -0,0 +1,20 @@ +from .base import Base +from typing import List + +class Jumpgate(Base): + range: int + faction: str + systems:List[str] = [] + + def update(self, d): + self.setlst('systems', d, 'connectedSystems', 'symbol') + self.seta('faction', d, 'factionSymbol') + self.seta('range', d, 'jumpRange') + + @classmethod + def ext(self): + return 'jmp' + + def path(self): + sector, system, symbol = self.symbol.split('-') + return f'atlas/{sector}/{system[0:1]}/{system}/{symbol}.{self.ext()}' diff --git a/nullptr/models/marketplace.py b/nullptr/models/marketplace.py index 8b9709e..96f8b33 100644 --- a/nullptr/models/marketplace.py +++ b/nullptr/models/marketplace.py @@ -17,5 +17,5 @@ class Marketplace(Base): return 'mkt' def path(self): - sector, system, symbol, _ = self.symbol.split('-') + sector, system, symbol = self.symbol.split('-') return f'atlas/{sector}/{system[0:1]}/{system}/{symbol}.{self.ext()}' diff --git a/nullptr/models/waypoint.py b/nullptr/models/waypoint.py index 027353d..967a597 100644 --- a/nullptr/models/waypoint.py +++ b/nullptr/models/waypoint.py @@ -14,8 +14,7 @@ class Waypoint(Base): self.seta('y', d) self.seta('type', d) self.seta('faction', d, 'faction.symbol') - if 'traits' in d: - self.traits = [mg(t, 'symbol') for t in d['traits'] ] + self.setlst('traits', d, 'traits', 'symbol') @classmethod def ext(self): diff --git a/nullptr/store.py b/nullptr/store.py index 0ec2c3b..194e276 100644 --- a/nullptr/store.py +++ b/nullptr/store.py @@ -7,11 +7,16 @@ from os.path import isfile, dirname, isdir import os import json from .util import * +from time import time class Store: def __init__(self, data_dir): self.data_dir = data_dir self.data = {} + self.dirty_objects = set() + + def dirty(self, obj): + self.dirty_objects.add(obj) def path(self, obj): return os.path.join(self.data_dir, obj.path()) @@ -23,7 +28,6 @@ class Store: with open(path) as f: data = json.load(f) data['store'] = self - data['dirty'] = False obj.__dict__ = data def store(self, obj): @@ -34,12 +38,14 @@ class Store: os.makedirs(path_dir, exist_ok=True) with open(path, 'w') as f: json.dump(data, f, indent=2) - obj.dirty = False def get(self, typ, symbol): + oid = f'{symbol}.{typ.ext()}' + if oid in self.data: + return self.data[oid] obj = typ(symbol, self) self.load(obj) - self.data[symbol] = obj + self.data[oid] = obj return obj def update(self, typ, symbol, data): @@ -68,6 +74,11 @@ class Store: def flush(self): - for obj in self.data.values(): - if obj.dirty: - self.store(obj) + it = 0 + start_time = time() + for obj in self.dirty_objects: + it += 1 + self.store(obj) + self.dirty_objects = set() + dur = time() - start_time + print(f'flush done {it} items {dur:.2f}')