diff --git a/nullptr/api.py b/nullptr/api.py index 4859e8f..ba589de 100644 --- a/nullptr/api.py +++ b/nullptr/api.py @@ -5,7 +5,7 @@ from nullptr.models.marketplace import Marketplace from nullptr.models.jumpgate import Jumpgate from nullptr.models.ship import Ship from .util import * -from time import sleep +from time import sleep, time class ApiError(Exception): def __init__(self, msg, code): super().__init__(msg) @@ -30,7 +30,11 @@ class Api: def request(self, method, path, data=None, need_token=True, params={}): try: - return self.request_once(method, path, data, need_token, params) + start = time() + result = self.request_once(method, path, data, need_token, params) + dur = time() - start + # print(f'api {dur:.03}') + return result except (ApiLimitError, requests.exceptions.Timeout): # print('oops, hit the limit. take a break') sleep(10) @@ -230,7 +234,7 @@ class Api: data = {} url = f'my/ships/{ship}/extract' if survey is not None: - data['survey'] = survey.api_dict() + data= survey.api_dict() url += '/survey' try: data = self.request('post', url, data=data) diff --git a/nullptr/central_command.py b/nullptr/central_command.py index 84148d3..c5742dd 100644 --- a/nullptr/central_command.py +++ b/nullptr/central_command.py @@ -3,7 +3,7 @@ from nullptr.models.ship import Ship from nullptr.missions import create_mission, get_mission_class from nullptr.models.waypoint import Waypoint from random import choice, randrange -from time import sleep +from time import sleep, time from threading import Thread from nullptr.atlas_builder import AtlasBuilder from nullptr.analyzer import Analyzer, Point @@ -64,6 +64,7 @@ class CentralCommand: while not self.stopping: did_step = True request_counter = self.api.requests_sent + start = time() while request_counter == self.api.requests_sent and did_step: did_step = self.tick() if request_counter == self.api.requests_sent: @@ -72,7 +73,11 @@ class CentralCommand: pass # print('nowork') self.store.flush() - sleep(0.5) + dur = time() - start + # print(f'step {dur:.03}') + zs = 0.5 - dur + if zs > 0: + sleep(zs) self.stopping = False def stop(self): @@ -137,6 +142,17 @@ class CentralCommand: self.assign_hauler(s) elif s.role == 'surveyor': self.assign_survey(s) + elif s.role == 'miner': + self.assign_mine(s) + + def assign_mine(self, s): + if s.crew is None: + raise CentralCommandError('ship has no crew') + w = s.crew.site + resources = s.crew.resources + self.init_mission(s, 'mine') + self.smipa(s, 'site', w) + self.smipa(s, 'resources', resources) def assign_survey(self, s): if s.crew is None: @@ -226,7 +242,7 @@ class CentralCommand: metal_w = self.find_metal(system) metal = self.store.get('Crew', 'METAL', create=True) metal.site = metal_w - metal.resources = ['COPPER_ORE','IRON_ORE'] + metal.resources = ['COPPER_ORE','IRON_ORE','ALUMINUM_ORE'] gas = self.store.get('Crew', 'GAS', create=True) gas.site = gas_w gas.resources = ['HYDROCARBON','LIQUID_HYDROGEN','LIQUID_NITROGEN'] diff --git a/nullptr/missions/extraction.py b/nullptr/missions/extraction.py new file mode 100644 index 0000000..8d0e9d8 --- /dev/null +++ b/nullptr/missions/extraction.py @@ -0,0 +1,28 @@ +from nullptr.missions.base import BaseMission + +class ExtractionMission(BaseMission): + def find_hauler(self, r): + for s in self.store.all('Ship'): + if s.mission != 'haul': continue + if s.location != self.ship.location: + continue + if s.mission_status != 'load': + continue + if r not in s.mission_state['resources']: continue + return s + return None + + def step_unload(self): + if len(self.ship.cargo) == 0: + return 'done' + r = list(self.ship.cargo.keys())[0] + amt = self.ship.cargo[r] + h = self.find_hauler(r) + if h is None: + self.api.jettison(self.ship, r) + else: + space = h.cargo_space() + amt = min(space, amt) + if amt > 0: + self.api.transfer(self.ship, h, r, amt) + return 'more' \ No newline at end of file diff --git a/nullptr/missions/mine.py b/nullptr/missions/mine.py index e41e1cc..c7eaa3b 100644 --- a/nullptr/missions/mine.py +++ b/nullptr/missions/mine.py @@ -3,15 +3,16 @@ from nullptr.models.waypoint import Waypoint from nullptr.models.survey import Survey from nullptr.models.contract import Contract from nullptr.util import * +from nullptr.missions.extraction import ExtractionMission -class MiningMission(BaseMission): +class MiningMission(ExtractionMission): @classmethod def params(cls): return { 'site': MissionParam(Waypoint, True), 'resources': MissionParam(list, True) } - p + def start_state(self): return 'travel-to' @@ -20,7 +21,7 @@ class MiningMission(BaseMission): **self.travel_steps('to', 'site', 'extract'), 'extract': (self.step_extract, { 'more': 'extract', - 'full': 'unload' + 'done': 'unload' }), 'unload': (self.step_unload, { 'more': 'unload', @@ -29,36 +30,31 @@ class MiningMission(BaseMission): } def get_survey(self): - resource = self.st('resource') + resources = self.st('resources') site = self.rst(Waypoint,'site') + best_score = 0 + best_survey = None # todo optimize for s in self.store.all(Survey): - if resource in s.deposits and site.symbol == s.waypoint: - return s - return None + if site != s.waypoint: + continue + good = len([1 for r in s.deposits if r in resources]) + total = len(s.deposits) + score = good / total + if score > best_score: + best_score = score + best_survey = s + return best_survey def step_extract(self): survey = self.get_survey() - print('using survey:', str(survey)) result = self.api.extract(self.ship, survey) symbol = sg(result,'extraction.yield.symbol') units = sg(result,'extraction.yield.units') - print('extracted:', units, symbol) self.next_step = self.ship.cooldown - if self.ship.cargo_units < self.ship.cargo_capacity: + if self.ship.cargo_space() > 5: return 'more' else: return 'done' - def step_dispose(self): - contract = self.rst(Contract, 'contract') - typs = self.ship.nondeliverable_cargo(contract) - if len(typs) > 0: - self.api.jettison(self.ship, typs[0]) - if len(typs) > 1: - return 'more' - elif self.ship.cargo_units > self.ship.cargo_capacity - 3: - return 'full' - else: - return 'done' - + \ No newline at end of file diff --git a/nullptr/missions/siphon.py b/nullptr/missions/siphon.py index 3587517..c191a41 100644 --- a/nullptr/missions/siphon.py +++ b/nullptr/missions/siphon.py @@ -1,7 +1,8 @@ -from nullptr.missions.base import BaseMission, MissionParam +from nullptr.missions.base import MissionParam +from nullptr.missions.extraction import ExtractionMission from nullptr.models.waypoint import Waypoint -class SiphonMission(BaseMission): +class SiphonMission(ExtractionMission): def start_state(self): return 'travel-to' @@ -18,32 +19,7 @@ class SiphonMission(BaseMission): return 'more' else: return 'full' - - def find_hauler(self, r): - for s in self.store.all('Ship'): - if s.mission != 'haul': continue - if s.location != self.ship.location: - continue - if s.mission_status != 'load': - continue - if r not in s.mission_state['resources']: continue - return s - return None - - def step_unload(self): - if len(self.ship.cargo) == 0: - return 'done' - r = list(self.ship.cargo.keys())[0] - amt = self.ship.cargo[r] - h = self.find_hauler(r) - if h is None: - self.api.jettison(self.ship, r) - else: - space = h.cargo_space() - amt = min(space, amt) - if amt > 0: - self.api.transfer(self.ship, h, r, amt) - return 'more' + def steps(self): return { diff --git a/nullptr/models/survey.py b/nullptr/models/survey.py index 77b7667..408410b 100644 --- a/nullptr/models/survey.py +++ b/nullptr/models/survey.py @@ -18,6 +18,11 @@ class Survey(Base): def ext(cls): return 'svy' + def get_waypoint(self): + sym = '-'.join(self.symbol.split('-')[:3]) + return self.store.get('Waypoint', sym, create=True) + + def is_expired(self): return time() > self.expires or self.exhausted @@ -28,7 +33,7 @@ class Survey(Base): def api_dict(self): return { 'signature': self.symbol, - 'symbol': self.waypoint, + 'symbol': self.waypoint.symbol, 'deposits': [{'symbol': d} for d in self.deposits], 'expiration': self.expires_str, 'size': size_names[self.size]