store fixes and probe role
This commit is contained in:
parent
188ef320cc
commit
7d92a45d12
@ -153,8 +153,7 @@ class Analyzer:
|
||||
def prices(self, system):
|
||||
prices = {}
|
||||
for m in self.store.all_members(system, Marketplace):
|
||||
for p in m.prices.values():
|
||||
r = p['symbol']
|
||||
for r, p in m.prices.items():
|
||||
if not r in prices:
|
||||
prices[r] = []
|
||||
prices[r].append({
|
||||
@ -168,7 +167,7 @@ class Analyzer:
|
||||
prices = self.prices(system)
|
||||
occupied_resources = set()
|
||||
for s in self.store.all('Ship'):
|
||||
if s.mission != 'haul':
|
||||
if s.mission != 'trade':
|
||||
continue
|
||||
occupied_resources.add(s.mission_state['resource'])
|
||||
best = None
|
||||
|
@ -1,7 +1,7 @@
|
||||
from nullptr.store import Store
|
||||
from nullptr.models.ship import Ship
|
||||
from nullptr.missions import create_mission, get_mission_class
|
||||
from random import choice
|
||||
from random import choice, randrange
|
||||
from time import sleep
|
||||
from threading import Thread
|
||||
from nullptr.atlas_builder import AtlasBuilder
|
||||
@ -106,10 +106,23 @@ class CentralCommand:
|
||||
|
||||
|
||||
def assign_mission(self, s):
|
||||
if s.role == 'hauler':
|
||||
self.assign_haul(s)
|
||||
if s.role == 'trader':
|
||||
self.assign_trade(s)
|
||||
elif s.role == 'probe':
|
||||
self.assign_probe(s)
|
||||
|
||||
def assign_haul(self, s):
|
||||
def assign_probe(self, s):
|
||||
system = s.location.system
|
||||
m = [m.waypoint for m in self.store.all_members(system, 'Marketplace')]
|
||||
m = self.analyzer.solve_tsp(m)
|
||||
hops = [w.symbol for w in m]
|
||||
start_hop = randrange(0, len(hops))
|
||||
print(f'Assigning {s} to probe {len(hops)} starting at {hops[start_hop]}')
|
||||
self.init_mission(s, 'probe')
|
||||
self.smipa(s, 'hops', hops)
|
||||
self.smipa(s, 'next-hop', start_hop)
|
||||
|
||||
def assign_trade(self, s):
|
||||
t = self.analyzer.find_trade(s.location.system)
|
||||
if t is None:
|
||||
print(f"No trade for {s} found. Idling")
|
||||
@ -117,7 +130,7 @@ class CentralCommand:
|
||||
self.smipa(s, 'seconds', 600)
|
||||
return
|
||||
print(f'assigning {s} to deliver {t.resource} from {t.source} to {t.dest} at a margin of {t.margin}')
|
||||
self.init_mission(s, 'haul')
|
||||
self.init_mission(s, 'trade')
|
||||
self.smipa(s, 'resource', t.resource)
|
||||
self.smipa(s, 'site', t.source)
|
||||
self.smipa(s, 'dest', t.dest)
|
||||
|
@ -20,6 +20,7 @@ class Commander(CommandLine):
|
||||
def __init__(self, data_dir='data'):
|
||||
store_file = os.path.join(data_dir, 'store.npt')
|
||||
hist_file = os.path.join(data_dir, 'cmd.hst')
|
||||
self.cred_file = os.path.join(data_dir, 'creds.txt')
|
||||
self.hist_file = hist_file
|
||||
if os.path.isfile(hist_file):
|
||||
readline.read_history_file(hist_file)
|
||||
@ -107,7 +108,7 @@ class Commander(CommandLine):
|
||||
if len(faction) > 50:
|
||||
self.agent.token = faction
|
||||
else:
|
||||
api.register(faction.upper().strip())
|
||||
self.do_register(faction)
|
||||
print('=== agent:')
|
||||
print(agent)
|
||||
print('=== ships')
|
||||
@ -126,6 +127,10 @@ class Commander(CommandLine):
|
||||
|
||||
def do_register(self, faction):
|
||||
self.api.register(faction.upper())
|
||||
with open(self.cred_file, 'w') as f:
|
||||
f.write(self.api.agent.symbol)
|
||||
f.write('\n')
|
||||
f.write(self.api.agent.token)
|
||||
pprint(self.api.agent)
|
||||
|
||||
######## Fleet #########
|
||||
@ -306,7 +311,7 @@ class Commander(CommandLine):
|
||||
pprint(self.ship.mission_state)
|
||||
|
||||
def do_role(self, role):
|
||||
roles = [None, 'hauler']
|
||||
roles = [None, 'trader', 'probe']
|
||||
if not self.has_ship(): return
|
||||
if role == 'none':
|
||||
role = None
|
||||
@ -407,7 +412,7 @@ class Commander(CommandLine):
|
||||
return
|
||||
_, m, _, _ = m[0]
|
||||
site = self.store.get(Waypoint, m.symbol)
|
||||
self.centcom.init_mission(self.ship, 'haul')
|
||||
self.centcom.init_mission(self.ship, 'trade')
|
||||
self.centcom.set_mission_param(self.ship, 'site', site)
|
||||
self.centcom.set_mission_param(self.ship, 'resource', resource)
|
||||
self.centcom.set_mission_param(self.ship, 'dest', destination)
|
||||
@ -432,18 +437,6 @@ class Commander(CommandLine):
|
||||
self.centcom.set_mission_param(self.ship, 'hops', markets)
|
||||
self.print_mission()
|
||||
|
||||
def do_sprobe(self):
|
||||
if not self.has_ship(): return
|
||||
system = self.ship.location.system
|
||||
m = [m.waypoint for m in self.store.all_members(system, 'Marketplace')]
|
||||
print("pre", path_dist(m))
|
||||
m = self.analyzer.solve_tsp(m)
|
||||
print("post", path_dist(m))
|
||||
hops = [w.symbol for w in m]
|
||||
self.centcom.init_mission(self.ship, 'probe')
|
||||
self.centcom.set_mission_param(self.ship, 'hops', hops)
|
||||
self.print_mission()
|
||||
|
||||
######## Travel #########
|
||||
def do_travel(self, dest):
|
||||
dest = self.resolve('Waypoint', dest)
|
||||
|
@ -1,6 +1,6 @@
|
||||
from nullptr.missions.survey import SurveyMission
|
||||
from nullptr.missions.mine import MiningMission
|
||||
from nullptr.missions.haul import HaulMission
|
||||
from nullptr.missions.trade import TradeMission
|
||||
from nullptr.missions.travel import TravelMission
|
||||
from nullptr.missions.probe import ProbeMission
|
||||
from nullptr.missions.idle import IdleMission
|
||||
@ -10,7 +10,7 @@ def get_mission_class( mtype):
|
||||
types = {
|
||||
'survey': SurveyMission,
|
||||
'mine': MiningMission,
|
||||
'haul': HaulMission,
|
||||
'trade': TradeMission,
|
||||
'travel': TravelMission,
|
||||
'probe': ProbeMission,
|
||||
'idle': IdleMission
|
||||
|
@ -49,7 +49,7 @@ class MiningMission(BaseMission):
|
||||
site = self.rst(Waypoint,'site')
|
||||
# todo optimize
|
||||
for s in self.store.all(Survey):
|
||||
if resource in s.deposits and site.symbol == s.waypoint():
|
||||
if resource in s.deposits and site.symbol == s.waypoint:
|
||||
return s
|
||||
return None
|
||||
|
||||
|
@ -2,7 +2,7 @@ from nullptr.missions.base import BaseMission, MissionParam
|
||||
from nullptr.models.waypoint import Waypoint
|
||||
from nullptr.models.survey import Survey
|
||||
from nullptr.models.contract import Contract
|
||||
class HaulMission(BaseMission):
|
||||
class TradeMission(BaseMission):
|
||||
def start_state(self):
|
||||
return 'travel-to'
|
||||
|
@ -15,6 +15,9 @@ class Reference:
|
||||
def resolve(self):
|
||||
return self.store.get(self.typ, self.symbol)
|
||||
|
||||
def f(self, detail):
|
||||
return f'{self.symbol}.{self.typ.ext()}'
|
||||
|
||||
def __repr__(self):
|
||||
return f'*REF*{self.symbol}.{self.typ.ext()}'
|
||||
|
||||
@ -46,6 +49,9 @@ class Base:
|
||||
def define(self):
|
||||
pass
|
||||
|
||||
def created(self):
|
||||
pass
|
||||
|
||||
def __hash__(self):
|
||||
return hash((str(type(self)), self.symbol))
|
||||
|
||||
@ -84,12 +90,16 @@ class Base:
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if not name.startswith('_') and not self._disable_dirty:
|
||||
self.store.dirty(self)
|
||||
self.dirty()
|
||||
if issubclass(type(value), Base):
|
||||
value = Reference.create(value)
|
||||
super().__setattr__(name, value)
|
||||
|
||||
def __getattribute__(self, nm):
|
||||
if nm == 'system':
|
||||
return self.get_system()
|
||||
if nm == 'waypoint':
|
||||
return self.get_waypoint()
|
||||
val = super().__getattribute__(nm)
|
||||
if type(val) == Reference:
|
||||
val = val.resolve()
|
||||
|
@ -5,7 +5,6 @@ from dataclasses import field
|
||||
class Jumpgate(Base):
|
||||
def define(self):
|
||||
self.connections: list = []
|
||||
self.system = self.get_system()
|
||||
|
||||
def update(self, d):
|
||||
getter = self.store.getter(Waypoint, create=True)
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
from .base import Base
|
||||
from .base import Base, Reference
|
||||
from time import time
|
||||
from nullptr.util import *
|
||||
from dataclasses import field, dataclass
|
||||
@ -32,12 +32,9 @@ class Marketplace(Base):
|
||||
self.exchange:list = []
|
||||
self.prices:dict = {}
|
||||
self.last_prices:int = 0
|
||||
self.set_waypoint()
|
||||
self.system = self.get_system()
|
||||
|
||||
def set_waypoint(self):
|
||||
waypoint = self.store.get(Waypoint, self.symbol, create=True)
|
||||
self.waypoint = waypoint
|
||||
def get_waypoint(self):
|
||||
return self.store.get('Waypoint', self.symbol, create=True)
|
||||
|
||||
def is_fuel(self):
|
||||
return self.imports + self.exports + self.exchange == ['FUEL']
|
||||
@ -51,7 +48,7 @@ class Marketplace(Base):
|
||||
e = self.prices[symbol] = MarketEntry()
|
||||
buy = mg(g, 'purchasePrice')
|
||||
sell = mg(g, 'sellPrice')
|
||||
volume = mg(g, 'tradeVolumes')
|
||||
volume = mg(g, 'tradeVolume')
|
||||
supply = SUPPLY.index(mg(g, 'supply'))
|
||||
activity = ACTIVITY.index(sg(g, 'activity','STRONG'))
|
||||
e.add(buy, sell, volume, supply, activity)
|
||||
@ -68,12 +65,12 @@ class Marketplace(Base):
|
||||
def buy_price(self, resource):
|
||||
if resource not in self.prices:
|
||||
return None
|
||||
return self.prices[resource]['buy']
|
||||
return self.prices[resource].buy
|
||||
|
||||
def volume(self, resource):
|
||||
if resource not in self.prices:
|
||||
return None
|
||||
return self.prices[resource]['volume']
|
||||
return self.prices[resource].volume
|
||||
|
||||
def sellable_items(self, resources):
|
||||
return [r for r in resources if r in self.prices]
|
||||
|
@ -28,7 +28,7 @@ class Survey(Base):
|
||||
def api_dict(self):
|
||||
return {
|
||||
'signature': self.symbol,
|
||||
'symbol': self.waypoint(),
|
||||
'symbol': self.waypoint,
|
||||
'deposits': [{'symbol': d} for d in self.deposits],
|
||||
'expiration': self.expires_str,
|
||||
'size': size_names[self.size]
|
||||
|
@ -12,7 +12,6 @@ class Waypoint(Base):
|
||||
self.traits:list = []
|
||||
self.faction:str = ''
|
||||
self.is_under_construction:bool = False
|
||||
self.system = self.get_system()
|
||||
self.uncharted = True
|
||||
|
||||
|
||||
@ -25,6 +24,9 @@ class Waypoint(Base):
|
||||
self.setlst('traits', d, 'traits', 'symbol')
|
||||
self.uncharted = 'UNCHARTED' in self.traits
|
||||
|
||||
def created(self):
|
||||
self.get_system()
|
||||
|
||||
def distance(self, other):
|
||||
return int(sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2))
|
||||
|
||||
|
@ -72,6 +72,7 @@ class ChunkHeader:
|
||||
class Store:
|
||||
def __init__(self, data_file, verbose=False):
|
||||
self.init_models()
|
||||
self.data_file = data_file
|
||||
self.data_dir = os.path.dirname(data_file)
|
||||
self.fil = open_file(data_file)
|
||||
self.data = {m: {} for m in self.models}
|
||||
@ -90,6 +91,9 @@ class Store:
|
||||
return
|
||||
print(m)
|
||||
|
||||
def f(self, detail):
|
||||
return f'Store {self.data_file}'
|
||||
|
||||
def close(self):
|
||||
self.flush()
|
||||
self.fil.close()
|
||||
@ -112,6 +116,9 @@ class Store:
|
||||
buf = BytesIO(data)
|
||||
p = StoreUnpickler(buf, self)
|
||||
obj = p.load()
|
||||
x = self.get(type(obj), obj.symbol)
|
||||
if x is not None and x in self.dirty_objects:
|
||||
self.dirty_objects.remove(obj)
|
||||
obj._file_offset = offset
|
||||
self.hold(obj)
|
||||
|
||||
@ -138,6 +145,8 @@ class Store:
|
||||
offset = self.fil.tell()
|
||||
|
||||
dur = time() - start_time
|
||||
# just in case any temp objects were created
|
||||
self.dirty_objects = set()
|
||||
self.p(f'Loaded {cnt} objects in {dur:.2f} seconds')
|
||||
self.p(f'Fragmented space: {free} / {total} bytes')
|
||||
|
||||
@ -210,14 +219,15 @@ class Store:
|
||||
symbol = obj.symbol
|
||||
obj.store = self
|
||||
self.data[typ][symbol] = obj
|
||||
if hasattr(obj, 'system'):
|
||||
system_str = obj.get_system().symbol
|
||||
if type(obj).__name__ in ['Waypoint','Marketplace', 'Jumpgate', 'Survey']:
|
||||
system_str = obj.system.symbol
|
||||
if system_str not in self.system_members:
|
||||
self.system_members[system_str] = set()
|
||||
self.system_members[system_str].add(obj)
|
||||
|
||||
def create(self, typ, symbol):
|
||||
obj = typ(symbol, self)
|
||||
obj.created()
|
||||
self.hold(obj)
|
||||
self.dirty(obj)
|
||||
return obj
|
||||
|
Loading…
Reference in New Issue
Block a user