diff --git a/tooling/econ-sim/src/db.rs b/tooling/econ-sim/src/db.rs index 7d3b7e89b..bd97d4812 100644 --- a/tooling/econ-sim/src/db.rs +++ b/tooling/econ-sim/src/db.rs @@ -282,12 +282,18 @@ fn load_gate_links(conn: &Connection) -> Vec { } fn load_corp_presences(conn: &Connection) -> Vec { + // Resolve body/station location_id back to system_id via LEFT JOINs. + // corp_presence.location_type is 'body' | 'station' per schema. let mut stmt = conn .prepare( - "SELECT corp_id, location_id, primary_operation - FROM corp_presence - WHERE location_type = 'system' - ORDER BY location_id, corp_id", + "SELECT cp.corp_id, + COALESCE(b.system_id, s.system_id) AS system_id, + cp.primary_operation + FROM corp_presence cp + LEFT JOIN bodies b ON cp.location_type = 'body' AND cp.location_id = b.body_id + LEFT JOIN stations s ON cp.location_type = 'station' AND cp.location_id = s.station_id + WHERE COALESCE(b.system_id, s.system_id) IS NOT NULL + ORDER BY system_id, cp.corp_id", ) .expect("prepare corp_presence"); diff --git a/tooling/economy-db/import_economics.py b/tooling/economy-db/import_economics.py index 27dbf434d..f831c0846 100755 --- a/tooling/economy-db/import_economics.py +++ b/tooling/economy-db/import_economics.py @@ -418,6 +418,54 @@ def sync_corporations( # Corp presence population # --------------------------------------------------------------------------- +def _resolve_hq_location( + conn: sqlite3.Connection, + system_id: str, + headquarters_body: str | None, +) -> tuple[str, str] | None: + """Resolve a corp's HQ to a (location_id, location_type) pair. + + Resolution order: + 1. Use headquarters_body from corporations table if set (body or station). + 2. Most-populated body in the system. + 3. Any body in the system. + 4. Any station in the system. + Returns None if no body or station found. + """ + if headquarters_body: + # Determine whether it's a body or station + body = conn.execute( + "SELECT body_id FROM bodies WHERE body_id = ?", (headquarters_body,) + ).fetchone() + if body: + return (headquarters_body, "body") + station = conn.execute( + "SELECT station_id FROM stations WHERE station_id = ?", + (headquarters_body,), + ).fetchone() + if station: + return (headquarters_body, "station") + + # Most-populated body + body = conn.execute( + """SELECT body_id FROM bodies WHERE system_id = ? + ORDER BY population DESC LIMIT 1""", + (system_id,), + ).fetchone() + if body: + return (body[0], "body") + + # Any station + station = conn.execute( + "SELECT station_id FROM stations WHERE system_id = ? LIMIT 1", + (system_id,), + ).fetchone() + if station: + return (station[0], "station") + + return None + + def import_corp_presence( conn: sqlite3.Connection, wiki_corps: list[dict], @@ -426,14 +474,22 @@ def import_corp_presence( ) -> int: """Populate corp_presence from wiki headquarters data. - Each corporation gets one presence row at its headquarters system. - primary_operation is set to the first commodity tag that matches a known - commodity ID, or None if no commodity tags are present. + Each corporation gets one presence row at its headquarters body or station. + location_type is 'body' or 'station' per schema (D-182). + primary_operation is set to the first commodity tag matching a known commodity ID. """ valid_systems = { r[0] for r in conn.execute("SELECT system_id FROM star_systems").fetchall() } + # Load headquarters_body from corporations table (set during import) + hq_body_map: dict[str, str | None] = { + r[0]: r[1] + for r in conn.execute( + "SELECT corp_id, headquarters_body FROM corporations" + ).fetchall() + } + rows = [] skipped = [] for corp in wiki_corps: @@ -444,10 +500,20 @@ def import_corp_presence( if system_id not in valid_systems: skipped.append(f"{corp['corp_id']} (system '{system_id}' not in DB)") continue + + hq_body = hq_body_map.get(corp["corp_id"]) + location = _resolve_hq_location(conn, system_id, hq_body) + if not location: + skipped.append( + f"{corp['corp_id']} (no body/station found in system '{system_id}')" + ) + continue + + location_id, location_type = location primary_op = next( (tag for tag in corp.get("tags", []) if tag in commodity_ids), None ) - rows.append((corp["corp_id"], system_id, "system", primary_op)) + rows.append((corp["corp_id"], location_id, location_type, primary_op)) if skipped: for s in skipped: