from core.chat_blob import ChatBlob from core.command_param_types import Any from core.db import DB from core.decorators import instance, command from core.text import Text @instance() class WhompahController: def inject(self, registry): self.db: DB = registry.get_instance("db") self.text: Text = registry.get_instance("text") def pre_start(self): self.db.load_sql_file(self.module_dir + "/sql/" + "whompah_cities.sql", pre_optimized=True) self.db.create_view("whompah_cities") self.db.create_view("whompah_cities_rel") @command(command="whompah", params=[], access_level="all", description="Show list of whompah cities") def whompah_list_cmd(self, request): cities = self.db.query("SELECT id, city_name, zone, faction, short_name FROM whompah_cities ORDER BY city_name") blob = "" for city in cities: blob += f"{self.text.get_formatted_faction(city.faction.lower(), city.city_name)} " \ f"({self.text.make_tellcmd(city.short_name, f'whompah {city.short_name}')})\n" return ChatBlob("Whompah Cities", blob) @command(command="whompah", params=[Any("city1"), Any("city2")], access_level="all", description="Show whompah route between two cities") def whompah_travel_cmd(self, request, city_name1, city_name2): city1 = self.get_whompah_city(city_name1) city2 = self.get_whompah_city(city_name2) if not city1: return f"Could not find whompah city {city_name1}." elif not city2: return f"Could not find whompah city {city_name2}." data = self.db.query("SELECT w1.*, w2.city2_id AS city_rel FROM whompah_cities w1 " "JOIN whompah_cities_rel w2 ON w1.id = w2.city1_id") cities = {} for city in data: rel = cities.get(city.id, {}).get("rel", []) rel.append(city.city_rel) cities[city.id] = city cities[city.id]["rel"] = rel path = self.format_path(self.find_path(cities, city1.id, city2.id)) return " -> ".join(path) @command(command="whompah", params=[Any("city")], access_level="all", description="Show whompah destinations for a city") def whompah_city_cmd(self, request, city_name): city = self.get_whompah_city(city_name) if not city: return f"Could not find whompah city {city_name}." cities = self.db.query("SELECT w2.* FROM whompah_cities_rel w1 " "JOIN whompah_cities w2 ON w1.city2_id = w2.id " "WHERE w1.city1_id = ?", [city.id]) msg = f"From {city.city_name} you can get to: " msg += ", ".join(map(lambda x: f"{self.text.get_formatted_faction(x.faction.lower(), x.city_name)} " f"({x.short_name})", cities)) return msg def get_whompah_city(self, city): return self.db.query_single("SELECT id, city_name, zone, faction, short_name FROM whompah_cities " "WHERE city_name LIKE ? " "OR short_name LIKE ?", [city, city]) def find_path(self, cities, start_city_id, end_city_id): def get_and_remove(key): value = cities[key] del cities[key] return value end_city = get_and_remove(end_city_id) if start_city_id == end_city_id: return end_city # create stack and initialize # start with ending city and traverse backwards so we don't have to reverse the result stack = [end_city] while stack: root = stack.pop(0) for rel in root["rel"]: if rel in cities: c = get_and_remove(rel) c["parent"] = root if c["id"] == start_city_id: return c stack.append(c) return None def format_path(self, path): result = [] root = path while root: result.append(self.text.get_formatted_faction(root["faction"].lower(), root["city_name"])) root = root.get("parent") return result