diff --git a/nullptr/analyzer.py b/nullptr/analyzer.py index c8c5dae..b7bba36 100644 --- a/nullptr/analyzer.py +++ b/nullptr/analyzer.py @@ -1,7 +1,28 @@ from nullptr.models.marketplace import Marketplace from nullptr.models.jumpgate import Jumpgate from nullptr.models.system import System +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 @@ -15,28 +36,22 @@ class Analyzer: def get_jumpgate(self, system): gates = self.store.all_members(system, Jumpgate) return next(gates, None) - - def find_path(self, orig, to): - if orig == to: return [] - jg = self.get_jumpgate(orig) - if jg is None: - print(f'{orig} no jg') - return None - best_distance = orig.distance(to) - best_hop = None - for hop_str in jg.systems: - hop = self.store.get(System, hop_str) - if hop is None: - print(f'{hop_str} hopnon') - continue - dist = hop.distance(to) - if dist < best_distance: - best_distance = dist - best_hop = hop - if best_hop is None: - print('nobest') - return None - print(best_hop, best_distance) - tail = self.find_path(best_hop, to) - if tail is None: return None - return [best_hop] + tail + + + def find_path(self, orig, to, depth=100): + if depth < 1: return None + 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: + system = self.store.get(System, s) + if system is None: continue + dest.add(SearchNode(system, o)) + if len(dest) == 0: return None + return self.find_path(dest, to, depth-1) diff --git a/nullptr/commander.py b/nullptr/commander.py index de6bed2..d6b7f2f 100644 --- a/nullptr/commander.py +++ b/nullptr/commander.py @@ -87,5 +87,7 @@ class Commander(CommandLine): def do_path(self): orig = self.ask_obj(System, 'from: ') dest = self.ask_obj(System, 'to: ') + # orig = self.store.get(System, 'X1-KS52') + # dest = self.store.get(System, 'X1-DA90') path = self.analyzer.find_path(orig, dest) pprint(path) diff --git a/nullptr/models/base.py b/nullptr/models/base.py index d22b0b4..20c9b9b 100644 --- a/nullptr/models/base.py +++ b/nullptr/models/base.py @@ -12,7 +12,10 @@ class Base: self.symbol = symbol def __hash__(self): - return hash(self.symbol) + return hash((str(type(self)), self.symbol)) + + def __eq__(self, other): + return self.symbol == other.symbol and type(self) == type(other) def seta(self, attr, d, name=None): if name is None: diff --git a/nullptr/models/system.py b/nullptr/models/system.py index 0dab3d6..9568fe0 100644 --- a/nullptr/models/system.py +++ b/nullptr/models/system.py @@ -21,4 +21,4 @@ class System(Base): return f'atlas/{sector}/{symbol[0:1]}/{self.symbol}.{self.ext()}' def distance(self, other): - return sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2) + return int(sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2)) diff --git a/nullptr/store.py b/nullptr/store.py index 275fe73..3ac660d 100644 --- a/nullptr/store.py +++ b/nullptr/store.py @@ -71,6 +71,7 @@ class Store: self.data[typ][symbol] = obj if issubclass(typ, SystemMember): system_str = obj.system() + if system_str not in self.system_members: self.system_members[system_str] = set() self.system_members[system_str].add(obj) @@ -101,6 +102,8 @@ class Store: def all_members(self, system, typ=None): if type(system) == System: system = system.symbol + if system not in self.system_members: + return for m in self.system_members[system]: if typ is None or type(m) == typ: yield m