|
@@ -0,0 +1,644 @@
|
|
|
+# processing the lines from the server ***
|
|
|
+
|
|
|
+ if line.startswith("The shortest path (") or line.startswith(" TO > "):
|
|
|
+ self.linestate = "warpline"
|
|
|
+ self.lastwarp = 0
|
|
|
+ elif line.startswith(" Items Status Trading % of max OnBoard"):
|
|
|
+ self.linestate = "port"
|
|
|
+ elif line.startswith("<Thievery>"):
|
|
|
+ self.linestate = "thievery"
|
|
|
+ elif self.linestate == "warpline":
|
|
|
+ if line == "":
|
|
|
+ self.linestate = ""
|
|
|
+ else:
|
|
|
+ self.warpline(line)
|
|
|
+ elif self.linestate == "portcim" or self.linestate == "warpcim":
|
|
|
+ if line == ": ENDINTERROG":
|
|
|
+ self.linestate = ""
|
|
|
+ elif line == ": ":
|
|
|
+ self.linestate = "cim"
|
|
|
+ elif line == "":
|
|
|
+ self.linestate = ""
|
|
|
+ else:
|
|
|
+ if len(line) > 2:
|
|
|
+ self.cimline(line)
|
|
|
+ elif self.linestate == "cim":
|
|
|
+ if line == ": ENDINTERROG" or line == "":
|
|
|
+ self.linestate = ""
|
|
|
+ elif len(line) > 2:
|
|
|
+ if line.rstrip()[-1] == "%":
|
|
|
+ self.linestate = "portcim"
|
|
|
+ else:
|
|
|
+ self.linestate = "warpcim"
|
|
|
+ self.cimline(line)
|
|
|
+ elif self.linestate == "thievery":
|
|
|
+ self.thiefline(line)
|
|
|
+ elif line == ": ":
|
|
|
+ self.linestate = "cim"
|
|
|
+ elif line.startswith("Sector : "):
|
|
|
+ # Sector : 2565 in uncharted space.
|
|
|
+ self.linestate = "sector"
|
|
|
+ work = line.strip()
|
|
|
+ parts = re.split(r"\s+", work)
|
|
|
+ self.current_sector = int(parts[2])
|
|
|
+ elif self.linestate == "sector":
|
|
|
+ self.sectorline(line)
|
|
|
+ elif self.linestate == "port":
|
|
|
+ if line == "":
|
|
|
+ self.linestate = ""
|
|
|
+ else:
|
|
|
+ self.portline(line)
|
|
|
+ self.observer.emit("game-line", line)
|
|
|
+
|
|
|
+
|
|
|
+ def portline(self, line: str):
|
|
|
+ # Map these items to which keys
|
|
|
+ self.log.debug("portline({0}): {1}".format(self.current_sector, line))
|
|
|
+ mapto = {"Fuel": "fuel", "Organics": "org", "Equipment": "equ"}
|
|
|
+
|
|
|
+ if "%" in line:
|
|
|
+ # Fuel Ore Buying 2890 100% 0
|
|
|
+ work = line.replace("Fuel Ore", "Fuel").replace("%", "")
|
|
|
+ parts = re.split(r"\s+", work)
|
|
|
+ data = {
|
|
|
+ mapto[parts[0]]: {
|
|
|
+ "sale": parts[1][0],
|
|
|
+ "units": parts[2],
|
|
|
+ "pct": int(parts[3]),
|
|
|
+ }
|
|
|
+ }
|
|
|
+ # log.debug("Setting {0} to {1}".format(self.current_sector, data))
|
|
|
+ self.gamedata.set_port(self.current_sector, data)
|
|
|
+ # log.debug("NOW: {0}".format(self.gamedata.ports[self.current_sector]))
|
|
|
+
|
|
|
+ def thiefline(self, line: str):
|
|
|
+ self.log.debug("thiefline({0}): {1}".format(self.current_sector, line))
|
|
|
+ if "Suddenly you're Busted!" in line:
|
|
|
+ # Lets add it into the bust list
|
|
|
+ self.gamedata.set_bust(self.current_sector)
|
|
|
+ elif "(You realize the guards saw you last time!)" in line:
|
|
|
+ self.linestate = ""
|
|
|
+
|
|
|
+ def cimline(self, line: str):
|
|
|
+ # log.debug(self.linestate, ":", line)
|
|
|
+ if line[-1] == "%":
|
|
|
+ self.linestate = "portcim"
|
|
|
+
|
|
|
+ if self.linestate == "warpcim":
|
|
|
+ # warps
|
|
|
+ work = line.strip()
|
|
|
+ if work != "":
|
|
|
+ parts = re.split(r"(?<=\d)\s", work)
|
|
|
+ parts = [int(x) for x in parts]
|
|
|
+ sector = parts.pop(0)
|
|
|
+ self.gamedata.warp_to(sector, *parts)
|
|
|
+ elif self.linestate == "portcim":
|
|
|
+ # ports
|
|
|
+ work = line.replace("%", "")
|
|
|
+ parts = re.parts = re.split(r"(?<=\d)\s", work)
|
|
|
+
|
|
|
+ if len(parts) == 8:
|
|
|
+ sector = int(parts[0].strip())
|
|
|
+ data = dict()
|
|
|
+
|
|
|
+ def portBS(info):
|
|
|
+ if info[0] == "-":
|
|
|
+ bs = "B"
|
|
|
+ else:
|
|
|
+ bs = "S"
|
|
|
+ return (bs, int(info[1:].strip()))
|
|
|
+
|
|
|
+ data["fuel"] = dict()
|
|
|
+ data["fuel"]["sale"], data["fuel"]["units"] = portBS(parts[1])
|
|
|
+ data["fuel"]["pct"] = int(parts[2].strip())
|
|
|
+ data["org"] = dict()
|
|
|
+ data["org"]["sale"], data["org"]["units"] = portBS(parts[3])
|
|
|
+ data["org"]["pct"] = int(parts[4].strip())
|
|
|
+ data["equ"] = dict()
|
|
|
+ data["equ"]["sale"], data["equ"]["units"] = portBS(parts[5])
|
|
|
+ data["equ"]["pct"] = int(parts[6].strip())
|
|
|
+
|
|
|
+ # Store what this port is buying/selling
|
|
|
+ data["port"] = (
|
|
|
+ data["fuel"]["sale"] + data["org"]["sale"] + data["equ"]["sale"]
|
|
|
+ )
|
|
|
+ # Convert BBS/SBB to Class number 1-8
|
|
|
+ data["class"] = CLASSES_PORT[data["port"]]
|
|
|
+ self.gamedata.set_port(sector, data)
|
|
|
+ else:
|
|
|
+ self.linestate = "cim"
|
|
|
+
|
|
|
+
|
|
|
+ def sectorline(self, line: str):
|
|
|
+ self.log.debug("sector: {0} : {1}".format(self.current_sector, line))
|
|
|
+ if line.startswith("Beacon : "):
|
|
|
+ pass # get beacon text
|
|
|
+ elif line.startswith("Ports : "):
|
|
|
+ # Ports : Ballista, Class 1 (BBS)
|
|
|
+ self.sector_state = "port"
|
|
|
+ if "<=-DANGER-=>" in line:
|
|
|
+ # Port is destroyed
|
|
|
+ if self.current_sector in self.gamedata.ports:
|
|
|
+ del self.gamedata.ports[self.current_sector]
|
|
|
+ # elif "(StarDock)" not in line:
|
|
|
+ # Ports : Stargate Alpha I, Class 9 (Special) (StarDock)
|
|
|
+ else:
|
|
|
+ _, _, class_port = line.partition(", Class ")
|
|
|
+ c, port = class_port.split(" ", maxsplit=1)
|
|
|
+ c = int(c)
|
|
|
+ if "StarDock" in port:
|
|
|
+ port = "StarDock"
|
|
|
+ port = port.replace("(", "").replace(")", "")
|
|
|
+ data = {"port": port, "class": c}
|
|
|
+ self.gamedata.set_port(self.current_sector, data)
|
|
|
+
|
|
|
+ elif line.startswith("Planets : "):
|
|
|
+
|
|
|
+ # Planets : (O) Flipper
|
|
|
+ self.sector_state = "planet"
|
|
|
+ elif line.startswith("Traders : "):
|
|
|
+ self.sector_state = "trader"
|
|
|
+ elif line.startswith("Ships : "):
|
|
|
+ self.sector_state = "ship"
|
|
|
+ elif line.startswith("Fighters: "):
|
|
|
+ self.sector_state = "fighter"
|
|
|
+ elif line.startswith("NavHaz : "):
|
|
|
+ pass
|
|
|
+ elif line.startswith("Mines : "):
|
|
|
+ self.sector_state = "mine"
|
|
|
+ elif line.startswith(" "):
|
|
|
+ # continues
|
|
|
+ if self.sector_state == "mines":
|
|
|
+ pass
|
|
|
+ if self.sector_state == "planet":
|
|
|
+ pass
|
|
|
+ if self.sector_state == "trader":
|
|
|
+ pass
|
|
|
+ if self.sector_state == "ship":
|
|
|
+
|
|
|
+
|
|
|
+ elif len(line) > 8 and line[8] == ":":
|
|
|
+ self.sector_state = "normal"
|
|
|
+ elif line.startswith("Warps to Sector(s) :"):
|
|
|
+ # Warps to Sector(s) : 5468
|
|
|
+ _, _, work = line.partition(":")
|
|
|
+ # TO FIX: We are interested in (unexplored) sectors.
|
|
|
+ work = work.strip().replace("(", "").replace(")", "").replace(" - ", " ")
|
|
|
+ parts = [int(x) for x in work.split(" ")]
|
|
|
+ self.log.debug("Sectorline warps {0}".format(parts))
|
|
|
+ self.gamedata.warp_to(self.current_sector, *parts)
|
|
|
+ self.sector_state = "normal"
|
|
|
+ self.linestate = ""
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+# gamedata
|
|
|
+
|
|
|
+PORT_CLASSES = {
|
|
|
+ 1: "BBS",
|
|
|
+ 2: "BSB",
|
|
|
+ 3: "SBB",
|
|
|
+ 4: "SSB",
|
|
|
+ 5: "SBS",
|
|
|
+ 6: "BSS",
|
|
|
+ 7: "SSS",
|
|
|
+ 8: "BBB",
|
|
|
+}
|
|
|
+CLASSES_PORT = {v: k for k, v in PORT_CLASSES.items()}
|
|
|
+
|
|
|
+
|
|
|
+class GameData(object):
|
|
|
+ def __init__(self, usergame: tuple):
|
|
|
+ # Construct the GameData storage object
|
|
|
+ self.usergame = usergame
|
|
|
+ self.warps = {}
|
|
|
+ self.ports = {}
|
|
|
+ self.busts = (
|
|
|
+ {}
|
|
|
+ ) # Added for evilTrade, just contains sector of port and datetime
|
|
|
+ self.config = {}
|
|
|
+ # 10 = 300 bytes
|
|
|
+ self.warp_groups = 10
|
|
|
+ # 3 = 560 bytes
|
|
|
+ # 5 = 930 bytes
|
|
|
+ self.port_groups = 3
|
|
|
+ # Not sure, I don't think it will be big.
|
|
|
+ self.bust_groups = 5
|
|
|
+ self.activated = False # Did we activate the proxy? Not sure if this is the right spot to put it in.
|
|
|
+
|
|
|
+
|
|
|
+ def reset_ports(self):
|
|
|
+ self.ports = {}
|
|
|
+
|
|
|
+ def reset_warps(self):
|
|
|
+ self.warps = {}
|
|
|
+
|
|
|
+ def reset_busts(self):
|
|
|
+ # Ok well we won't ever use this since maint_busts() goes thru them all and filters out those that are 7 days or older
|
|
|
+ self.busts = {}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ def special_ports(self):
|
|
|
+ """ Save the special class ports 0, 9 """
|
|
|
+ return {
|
|
|
+ p: self.ports[p]
|
|
|
+ for p in self.ports
|
|
|
+ if "class" in self.ports[p] and self.ports[p]["class"] in (0, 9)
|
|
|
+ }
|
|
|
+
|
|
|
+ def save(self, *_):
|
|
|
+
|
|
|
+ def load(self):
|
|
|
+
|
|
|
+ def get_warps(self, sector: int):
|
|
|
+ if sector in self.warps:
|
|
|
+ return self.warps[sector]
|
|
|
+ return None
|
|
|
+
|
|
|
+ def warp_to(self, source: int, *dest):
|
|
|
+ """ connect sector source to destination.
|
|
|
+ """
|
|
|
+ log.debug("Warp {0} to {1}".format(source, dest))
|
|
|
+ if source not in self.warps:
|
|
|
+ self.warps[source] = set()
|
|
|
+
|
|
|
+ for d in dest:
|
|
|
+ if d not in self.warps[source]:
|
|
|
+ self.warps[source].add(d)
|
|
|
+
|
|
|
+ def get_config(self, key, default=None):
|
|
|
+ if key in self.config:
|
|
|
+ return self.config[key]
|
|
|
+ else:
|
|
|
+ if default is not None:
|
|
|
+ self.config[key] = default
|
|
|
+ return default
|
|
|
+
|
|
|
+ def set_config(self, key, value):
|
|
|
+ self.config.update({key: value})
|
|
|
+
|
|
|
+
|
|
|
+ def set_port(self, sector: int, data: dict):
|
|
|
+ log.debug("Port {0} : {1}".format(sector, data))
|
|
|
+ if sector not in self.ports:
|
|
|
+ self.ports[sector] = dict()
|
|
|
+ self.ports[sector].update(data)
|
|
|
+
|
|
|
+ if "port" not in self.ports[sector]:
|
|
|
+ # incomplete port type - can we "complete" it?
|
|
|
+
|
|
|
+ if all(x in self.ports for x in ["fuel", "org", "equ"]):
|
|
|
+ # We have all of the port types, so:
|
|
|
+ port = "".join(
|
|
|
+ [self.ports[sector][x]["sale"] for x in ["fuel", "org", "equ"]]
|
|
|
+ )
|
|
|
+ self.ports[sector]["port"] = port
|
|
|
+ self.ports[sector]["class"] = CLASSES_PORT[port]
|
|
|
+ log.debug("completed {0} : {1}".format(sector, self.ports[sector]))
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ def port_buying(self, sector: int, cargo: str):
|
|
|
+ """ Given a sector, is this port buying this?
|
|
|
+
|
|
|
+ cargo is a char (F/O/E)
|
|
|
+ """
|
|
|
+ cargo_to_index = {"F": 0, "O": 1, "E": 2}
|
|
|
+ cargo_types = ("fuel", "org", "equ")
|
|
|
+
|
|
|
+ cargo = cargo[0]
|
|
|
+ if sector not in self.ports:
|
|
|
+ log.warn("port_buying( {0}, {1}): sector unknown!".format(sector, cargo))
|
|
|
+ return False
|
|
|
+ port = self.ports[sector]
|
|
|
+ if "port" not in port:
|
|
|
+ log.warn("port_buying( {0}, {1}): port unknown!".format(sector, cargo))
|
|
|
+ return True
|
|
|
+ if sector in self.busts: # Abort! This given sector is a busted port!
|
|
|
+ log.warn(
|
|
|
+ "port_buying({0}, {1}): sector contains a busted port!".format(
|
|
|
+ sector, cargo
|
|
|
+ )
|
|
|
+ )
|
|
|
+ return False
|
|
|
+
|
|
|
+
|
|
|
+ cargo_index = cargo_to_index[cargo]
|
|
|
+ if port["port"] in ("Special", "StarDock"):
|
|
|
+ log.warn(
|
|
|
+ "port_buying( {0}, {1}): not buying (is {2})".format(
|
|
|
+ sector, cargo, port["port"]
|
|
|
+ )
|
|
|
+ )
|
|
|
+ return False
|
|
|
+ if port["port"][cargo_index] == "S":
|
|
|
+ log.warn("port_buying( {0}, {1}): not buying cargo".format(sector, cargo))
|
|
|
+ return False
|
|
|
+
|
|
|
+ # ok, they buy it, but *WILL THEY* really buy it?
|
|
|
+ cargo_key = cargo_types[cargo_index]
|
|
|
+ if cargo_key in port:
|
|
|
+ if int(port[cargo_key]["units"]) > 40:
|
|
|
+ log.warn(
|
|
|
+ "port_buying( {0}, {1}): Yes, buying {2}".format(
|
|
|
+ sector, cargo, port[cargo_key]["sale"]
|
|
|
+ )
|
|
|
+ )
|
|
|
+ return True
|
|
|
+ else:
|
|
|
+ log.warn(
|
|
|
+ "port_buying( {0}, {1}): No, units < 40 {2}".format(
|
|
|
+ sector, cargo, port[cargo_key]["sale"]
|
|
|
+
|
|
|
+ )
|
|
|
+ )
|
|
|
+ return False
|
|
|
+ else:
|
|
|
+ log.warn(
|
|
|
+ "port_buying( {0}, {1}): Yes, buying (but values unknown)".format(
|
|
|
+ sector, cargo
|
|
|
+ )
|
|
|
+ )
|
|
|
+ return True # unknown port, we're guess yes.
|
|
|
+ return False
|
|
|
+
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def port_burnt(port: dict):
|
|
|
+ """ Is this port burned out? """
|
|
|
+ if all(x in port for x in ["fuel", "org", "equ"]):
|
|
|
+ if all("pct" in port[x] for x in ["fuel", "org", "equ"]):
|
|
|
+ if (
|
|
|
+ port["equ"]["pct"] <= 20
|
|
|
+ or port["fuel"]["pct"] <= 20
|
|
|
+ or port["org"]["pct"] <= 20
|
|
|
+ ):
|
|
|
+ return True
|
|
|
+ return False
|
|
|
+ # Since we don't have any port information, hope for the best, assume it isn't burnt.
|
|
|
+ return False
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def flip(buy_sell):
|
|
|
+ # Invert B's and S's to determine if we can trade or not between ports.
|
|
|
+ return buy_sell.replace("S", "W").replace("B", "S").replace("W", "B")
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def port_trading(port1, port2):
|
|
|
+ # Given the port settings, can we trade between these?
|
|
|
+ if port1 == port2:
|
|
|
+ return False
|
|
|
+ if port1 in ("Special", "StarDock") or port2 in ("Special", "StarDock"):
|
|
|
+ return False
|
|
|
+
|
|
|
+ # Oops, hey, we are given port settings not a sector a port is in,
|
|
|
+ # So don't try to check it against the busted list.
|
|
|
+
|
|
|
+ p1 = [c for c in port1]
|
|
|
+ p2 = [c for c in port2]
|
|
|
+ rem = False
|
|
|
+ for i in range(3):
|
|
|
+ if p1[i] == p2[i]:
|
|
|
+ p1[i] = "X"
|
|
|
+ p2[i] = "X"
|
|
|
+ rem = True
|
|
|
+ if rem:
|
|
|
+ j1 = "".join(p1).replace("X", "")
|
|
|
+ j2 = "".join(p2).replace("X", "")
|
|
|
+ if j1 == "BS" and j2 == "SB":
|
|
|
+ return True
|
|
|
+ if j1 == "SB" and j2 == "BS":
|
|
|
+ return True
|
|
|
+
|
|
|
+ rport1 = GameData.flip(port1)
|
|
|
+
|
|
|
+ c = 0
|
|
|
+ match = []
|
|
|
+ for i in range(3):
|
|
|
+ if rport1[i] == port2[i]:
|
|
|
+ match.append(port2[i])
|
|
|
+ c += 1
|
|
|
+ if c > 1:
|
|
|
+ # Remove first match, flip it
|
|
|
+ f = GameData.flip(match.pop(0))
|
|
|
+ # Verify it is in there.
|
|
|
+ # so we're not matching SSS/BBB
|
|
|
+ if f in match:
|
|
|
+ return True
|
|
|
+ return False
|
|
|
+ return False
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def port_pct(port: dict):
|
|
|
+ # Make sure these exist in the port data given.
|
|
|
+ if all(x in port for x in ["fuel", "org", "equ"]):
|
|
|
+ return "{0},{1},{2}%".format(
|
|
|
+ GameData.color_pct(port["fuel"]["pct"]),
|
|
|
+ GameData.color_pct(port["org"]["pct"]),
|
|
|
+ GameData.color_pct(port["equ"]["pct"]),
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ return "---,---,---%"
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def port_show_part(sector: int, sector_port: dict):
|
|
|
+ return "{0:5} ({1}) {2}".format(
|
|
|
+ sector, sector_port["port"], GameData.port_pct(sector_port)
|
|
|
+ )
|
|
|
+
|
|
|
+ def port_above(self, port: dict, limit: int) -> bool:
|
|
|
+ if all(x in port for x in ["fuel", "org", "equ"]):
|
|
|
+ if all(
|
|
|
+ x in port and port[x]["pct"] >= limit for x in ["fuel", "org", "equ"]
|
|
|
+ ):
|
|
|
+ return True
|
|
|
+ else:
|
|
|
+ return False
|
|
|
+ # Port is unknown, we'll assume it is above the limit.
|
|
|
+ return True
|
|
|
+
|
|
|
+ def port_trade_show(self, sector: int, warp: int, limit: int = 90):
|
|
|
+ sector_port = self.ports[sector]
|
|
|
+ warp_port = self.ports[warp]
|
|
|
+
|
|
|
+ if self.port_above(sector_port, limit) and self.port_above(warp_port, limit):
|
|
|
+ # sector_pct = GameData.port_pct(sector_port)
|
|
|
+ # warp_pct = GameData.port_pct(warp_port)
|
|
|
+ return "{0} \xae\xcd\xaf {1}".format(
|
|
|
+ GameData.port_show_part(sector, sector_port),
|
|
|
+ GameData.port_show_part(warp, warp_port),
|
|
|
+ )
|
|
|
+ return None
|
|
|
+
|
|
|
+ @staticmethod
|
|
|
+ def port_show(sector: int, sector_port: dict, warp: int, warp_port: dict):
|
|
|
+ # sector_pct = GameData.port_pct(sector_port)
|
|
|
+ # warp_pct = GameData.port_pct(warp_port)
|
|
|
+ return "{0} -=- {1}".format(
|
|
|
+ GameData.port_show_part(sector, sector_port),
|
|
|
+ GameData.port_show_part(warp, warp_port),
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+ def find_nearest_tradepairs(self, sector: int, obj):
|
|
|
+ """ find nearest tradepair
|
|
|
+
|
|
|
+ When do we use good? When do we use ok?
|
|
|
+ """
|
|
|
+ searched = set()
|
|
|
+ if sector not in self.warps:
|
|
|
+ log.warn(":Sector {0} not in warps.".format(sector))
|
|
|
+ obj.target_sector = None
|
|
|
+ return None
|
|
|
+ if sector in self.busts:
|
|
|
+ log.warn(":Sector {0} in busted".format(sector))
|
|
|
+ obj.target_sector = None
|
|
|
+ return None
|
|
|
+
|
|
|
+ # Start with the current sector
|
|
|
+ look = set((sector,))
|
|
|
+
|
|
|
+ while len(look) > 0:
|
|
|
+ log.warn("Searched [{0}]".format(searched))
|
|
|
+ log.warn("Checking [{0}]".format(look))
|
|
|
+ for s in look:
|
|
|
+ if s in self.ports:
|
|
|
+ # Ok, there's a port at least
|
|
|
+ sp = self.ports[s]
|
|
|
+ if sp["port"] in ("Special", "StarDock"):
|
|
|
+ continue
|
|
|
+ if self.port_burnt(sp):
|
|
|
+ continue
|
|
|
+ if "class" not in sp:
|
|
|
+ continue
|
|
|
+ if s in self.busts: # Check for busted port
|
|
|
+ continue
|
|
|
+ sc = sp["class"]
|
|
|
+
|
|
|
+ if s not in self.warps:
|
|
|
+ continue
|
|
|
+
|
|
|
+ log.warn("{0} has warps {1}".format(s, self.warps[s]))
|
|
|
+
|
|
|
+ # Ok, check for tradepairs.
|
|
|
+ for w in self.warps[s]:
|
|
|
+ if not w in self.warps:
|
|
|
+ continue
|
|
|
+ if not s in self.warps[w]:
|
|
|
+ continue
|
|
|
+ if not w in self.ports:
|
|
|
+ continue
|
|
|
+
|
|
|
+ # Ok, has possible port
|
|
|
+ cp = self.ports[w]
|
|
|
+ if cp["port"] in ("Special", "StarDock"):
|
|
|
+ continue
|
|
|
+ if self.port_burnt(cp):
|
|
|
+ continue
|
|
|
+ if "class" not in cp:
|
|
|
+ continue
|
|
|
+ if w in self.busts: # Check for busted
|
|
|
+ continue
|
|
|
+ cc = cp["class"]
|
|
|
+ log.warn("{0} {1} - {2} {3}".format(s, sc, w, cc))
|
|
|
+ if sc in (1, 5) and cc in (2, 4):
|
|
|
+ # Good!
|
|
|
+ log.warn("GOOD: {0}".format(s))
|
|
|
+ obj.target_sector = s
|
|
|
+ return s
|
|
|
+ if sc in (2, 4) and cc in (1, 5):
|
|
|
+ # Good!
|
|
|
+ log.warn("GOOD: {0}".format(s))
|
|
|
+ obj.target_sector = s
|
|
|
+ return s
|
|
|
+ # What about "OK" pairs?
|
|
|
+
|
|
|
+ # Ok, not found here.
|
|
|
+ searched.update(look)
|
|
|
+ step_from = look
|
|
|
+ look = set()
|
|
|
+
|
|
|
+ for s in step_from:
|
|
|
+ if s in self.warps:
|
|
|
+ look.update(self.warps[s])
|
|
|
+ # Look only contains warps we haven't searched
|
|
|
+ look = look.difference(searched)
|
|
|
+ yield
|
|
|
+ obj.target_sector = None
|
|
|
+ return None
|
|
|
+
|
|
|
+ def find_nearest_selling(
|
|
|
+ self, sector: int, selling: str, at_least: int = 100
|
|
|
+ ) -> int:
|
|
|
+ """ find nearest port that is selling at_least amount of this item
|
|
|
+
|
|
|
+ selling is 'f', 'o', or 'e'.
|
|
|
+ """
|
|
|
+ names = {"e": "equ", "o": "org", "f": "fuel"}
|
|
|
+ pos = {"f": 0, "o": 1, "e": 2}
|
|
|
+ sell = names[selling[0].lower()]
|
|
|
+ s_pos = pos[selling[0].lower()]
|
|
|
+ log.warn(
|
|
|
+ "find_nearest_selling({0}, {1}, {2}): {3}, {4}".format(
|
|
|
+ sector, selling, at_least, sell, s_pos
|
|
|
+ )
|
|
|
+ )
|
|
|
+ searched = set()
|
|
|
+ if sector not in self.warps:
|
|
|
+ log.warn("( {0}, {1}): sector not in warps".format(sector, selling))
|
|
|
+ return 0
|
|
|
+ if sector in self.busts:
|
|
|
+ log.warn(
|
|
|
+ "({0}, {1}): sector is in busted ports list".format(sector, selling)
|
|
|
+ )
|
|
|
+ return 0
|
|
|
+
|
|
|
+ # Start with the current sector
|
|
|
+ look = set((sector,))
|
|
|
+
|
|
|
+ while len(look) > 0:
|
|
|
+ for s in look:
|
|
|
+ if s in self.ports:
|
|
|
+ # Ok, possibly?
|
|
|
+ sp = self.ports[s]
|
|
|
+ if sp["port"] in ("Special", "StarDock"):
|
|
|
+ continue
|
|
|
+ if s in self.busts: # Busted!
|
|
|
+ continue
|
|
|
+ if sp["port"][s_pos] == "S":
|
|
|
+ # Ok, they are selling!
|
|
|
+ if sell in sp:
|
|
|
+ if int(sp[sell]["units"]) >= at_least:
|
|
|
+ log.warn(
|
|
|
+ "find_nearest_selling( {0}, {1}): {2} {3} units".format(
|
|
|
+ sector, selling, s, sp[sell]["units"]
|
|
|
+ )
|
|
|
+ )
|
|
|
+ return s
|
|
|
+ else:
|
|
|
+ # We know they sell it, but we don't know units
|
|
|
+ log.warn(
|
|
|
+ "find_nearest_selling( {0}, {1}): {2} {3}".format(
|
|
|
+ sector, selling, s, sp["port"]
|
|
|
+ )
|
|
|
+ )
|
|
|
+ return s
|
|
|
+ # Ok, not found here. Branch out.
|
|
|
+ searched.update(look)
|
|
|
+ step_from = look
|
|
|
+ look = set()
|
|
|
+ for s in step_from:
|
|
|
+ if s in self.warps:
|
|
|
+ look.update(self.warps[s])
|
|
|
+ # look only contains warps we haven't searched
|
|
|
+ look = look.difference(searched)
|
|
|
+ # Ok, we have run out of places to search
|
|
|
+ log.warn("find_nearest_selling( {0}, {1}) : failed".format(sector, selling))
|
|
|
+ return 0
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|