0ptr/nullptr/analyzer.py

85 lines
2.3 KiB
Python
Raw Normal View History

from nullptr.models.marketplace import Marketplace
from nullptr.models.jumpgate import Jumpgate
from nullptr.models.system import System
2023-06-21 07:32:31 +00:00
from nullptr.models.waypoint import Waypoint
from dataclasses import dataclass
@dataclass
class SearchNode:
system: System
parent: 'SearchNode'
def __hash__(self):
return hash(self.system.symbol)
def path(self):
result = []
n = self
while n is not None:
result.append(n.system)
n = n.parent
result.reverse()
return result
def __repr__(self):
return self.system.symbol
class Analyzer:
def __init__(self, store):
self.store = store
2023-06-14 14:55:45 +00:00
def find_markets(self, resource, sellbuy):
for m in self.store.all(Marketplace):
2023-06-21 07:32:31 +00:00
if sellbuy == 'sell':
resources = m.imports
elif sellbuy == 'buy':
resources = m.exports
elif sellbuy == 'exchange':
resources = m.exchange
if resource in resources:
yield m
def find_closest_market(self, resource, sellbuy, location):
2023-06-20 20:18:20 +00:00
if type(location) == str:
2023-06-21 07:32:31 +00:00
location = self.store.get(Waypoint, location)
market = None
distance = None
2023-06-21 07:32:31 +00:00
mkts = self.find_markets(resource, sellbuy)
for m in mkts:
system = self.store.get(System, m.system())
2023-06-21 07:32:31 +00:00
origin = self.store.get(System, location.system())
p = self.find_path(origin, system)
if p is None: continue
if distance is None or len(p) < distance:
market = m
distance = len(p)
return market
def get_jumpgate(self, system):
gates = self.store.all_members(system, Jumpgate)
return next(gates, None)
2023-06-14 19:26:46 +00:00
def find_path(self, orig, to, depth=100, seen=None):
if depth < 1: return None
2023-06-14 19:26:46 +00:00
if seen is None:
seen = set()
if type(orig) == System:
orig = set([SearchNode(orig,None)])
result = [n for n in orig if n.system==to]
if len(result) > 0:
return result[0].path()
dest = set()
for o in orig:
jg = self.get_jumpgate(o.system)
if jg is None: continue
for s in jg.systems:
2023-06-14 19:26:46 +00:00
if s in seen: continue
2023-06-14 13:54:32 +00:00
seen.add(s)
system = self.store.get(System, s)
if system is None: continue
dest.add(SearchNode(system, o))
2023-06-14 19:20:47 +00:00
if len(dest) == 0:
return None
2023-06-14 19:26:46 +00:00
return self.find_path(dest, to, depth-1, seen)