fix(simulation): resolve corp_presence location granularity bug (#805)
import_corp_presence() was inserting system IDs with location_type='system', violating the schema which expects body/station IDs (location_type='body'|'station'). Fix: - import_economics.py: add _resolve_hq_location() that picks the most-populated body in the HQ system (falling back to any body, then any station) - econ-sim/db.rs: load_corp_presences() now JOINs bodies/stations to recover system_id from body/station location_ids, dropping the 'system' filter Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -282,12 +282,18 @@ fn load_gate_links(conn: &Connection) -> Vec<GateLink> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_corp_presences(conn: &Connection) -> Vec<CorpPresence> {
|
fn load_corp_presences(conn: &Connection) -> Vec<CorpPresence> {
|
||||||
|
// 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
|
let mut stmt = conn
|
||||||
.prepare(
|
.prepare(
|
||||||
"SELECT corp_id, location_id, primary_operation
|
"SELECT cp.corp_id,
|
||||||
FROM corp_presence
|
COALESCE(b.system_id, s.system_id) AS system_id,
|
||||||
WHERE location_type = 'system'
|
cp.primary_operation
|
||||||
ORDER BY location_id, corp_id",
|
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");
|
.expect("prepare corp_presence");
|
||||||
|
|
||||||
|
|||||||
@@ -418,6 +418,54 @@ def sync_corporations(
|
|||||||
# Corp presence population
|
# 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(
|
def import_corp_presence(
|
||||||
conn: sqlite3.Connection,
|
conn: sqlite3.Connection,
|
||||||
wiki_corps: list[dict],
|
wiki_corps: list[dict],
|
||||||
@@ -426,14 +474,22 @@ def import_corp_presence(
|
|||||||
) -> int:
|
) -> int:
|
||||||
"""Populate corp_presence from wiki headquarters data.
|
"""Populate corp_presence from wiki headquarters data.
|
||||||
|
|
||||||
Each corporation gets one presence row at its headquarters system.
|
Each corporation gets one presence row at its headquarters body or station.
|
||||||
primary_operation is set to the first commodity tag that matches a known
|
location_type is 'body' or 'station' per schema (D-182).
|
||||||
commodity ID, or None if no commodity tags are present.
|
primary_operation is set to the first commodity tag matching a known commodity ID.
|
||||||
"""
|
"""
|
||||||
valid_systems = {
|
valid_systems = {
|
||||||
r[0] for r in conn.execute("SELECT system_id FROM star_systems").fetchall()
|
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 = []
|
rows = []
|
||||||
skipped = []
|
skipped = []
|
||||||
for corp in wiki_corps:
|
for corp in wiki_corps:
|
||||||
@@ -444,10 +500,20 @@ def import_corp_presence(
|
|||||||
if system_id not in valid_systems:
|
if system_id not in valid_systems:
|
||||||
skipped.append(f"{corp['corp_id']} (system '{system_id}' not in DB)")
|
skipped.append(f"{corp['corp_id']} (system '{system_id}' not in DB)")
|
||||||
continue
|
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(
|
primary_op = next(
|
||||||
(tag for tag in corp.get("tags", []) if tag in commodity_ids), None
|
(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:
|
if skipped:
|
||||||
for s in skipped:
|
for s in skipped:
|
||||||
|
|||||||
Reference in New Issue
Block a user