feat(topology): add seed data script for GHC-01 through GHC-05

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-09 20:52:11 +08:00
co-authored by Claude
parent e4b633e25d
commit adf3c60688
+621
View File
@@ -0,0 +1,621 @@
# topology_api/seed/seed_ghc01_to_ghc05.py
"""
Seed the topology database with GHC-01 through GHC-05 mission data.
Idempotent: can be run multiple times safely.
Usage:
PYTHONPATH="d:/My Coding Project/KSP_Project" python topology_api/seed/seed_ghc01_to_ghc05.py
"""
import json
from datetime import datetime, timezone
from topology_api.db import write_cursor
UTC = timezone.utc
def ts(s):
"""Parse ISO timestamp string to datetime."""
return datetime.fromisoformat(s).replace(tzinfo=UTC)
def seed():
with write_cursor() as cur:
# ============================================================
# PHASE 0: Clean existing data (reverse dependency order)
# ============================================================
cur.execute("DELETE FROM topology_connections")
cur.execute("DELETE FROM component_states")
cur.execute("DELETE FROM component_versions")
cur.execute("DELETE FROM ports")
cur.execute("DELETE FROM components")
cur.execute("DELETE FROM mission_events")
cur.execute("DELETE FROM missions")
cur.execute("DELETE FROM bases")
print("Cleared existing data.")
# ============================================================
# PHASE 1: Base
# ============================================================
cur.execute("""
INSERT INTO bases (id, code, name, description)
VALUES (gen_random_uuid(), 'guanghan', '广寒基地',
'月球东方海常驻月面基地')
ON CONFLICT (code) DO UPDATE SET name = EXCLUDED.name
RETURNING id
""")
base_id = cur.fetchone()["id"]
print(f"Base: guanghan ({base_id})")
# ============================================================
# PHASE 2: Missions
# ============================================================
mission_specs = [
("BL-01", "冰轮部署任务-01"),
("GHC-01", "广寒基地建设任务-01"),
("JC-01", "金蟾部署任务-01"),
("BL-02", "冰轮部署任务-02"),
("GHC-02", "广寒基地建设任务-02"),
("GHC-03", "广寒基地建设任务-03"),
("BL-03", "冰轮部署任务-03"),
("GHC-04", "广寒基地建设任务-04"),
("GHC-05", "广寒基地建设任务-05"),
]
mission_ids = {}
for code, title in mission_specs:
cur.execute("""
INSERT INTO missions (id, base_id, code, title, occurrence_status)
VALUES (gen_random_uuid(), %(base)s, %(code)s, %(title)s, 'occurred')
ON CONFLICT (base_id, code) DO UPDATE SET title = EXCLUDED.title
RETURNING id
""", {"base": base_id, "code": code, "title": title})
mission_ids[code] = cur.fetchone()["id"]
print(f"Missions: {len(mission_ids)}")
# ============================================================
# PHASE 3: Mission Events
# ============================================================
def add_event(mission_code, effective_at, event_order, event_type, title,
details=None, source_ref=None):
cur.execute("""
INSERT INTO mission_events
(id, mission_id, effective_at, event_order, event_type,
title, details, source_ref)
VALUES (gen_random_uuid(), %(mid)s, %(at)s, %(ord)s, %(typ)s,
%(title)s, %(det)s, %(ref)s)
ON CONFLICT (mission_id, effective_at, event_order) DO NOTHING
RETURNING id
""", {
"mid": mission_ids[mission_code], "at": effective_at,
"ord": event_order, "typ": event_type, "title": title,
"det": json.dumps(details) if details else None,
"ref": source_ref,
})
row = cur.fetchone()
if row:
return row["id"]
cur.execute("""
SELECT id FROM mission_events
WHERE mission_id = %(mid)s AND effective_at = %(at)s
AND event_order = %(ord)s
""", {"mid": mission_ids[mission_code], "at": effective_at, "ord": event_order})
return cur.fetchone()["id"]
events = {}
# ---- BL-01 ----
events["BL-01_0"] = add_event("BL-01",
ts("2024-04-19T22:58:00Z"), 0, "component_introduced",
"冰轮一号着陆东方海", source_ref="Timeline.md BL-01")
# ---- GHC-01 ----
events["GHC-01_0"] = add_event("GHC-01",
ts("2024-06-16T07:23:00Z"), 0, "component_introduced",
"广寒核心舱着陆东方海,引擎模块分离坠毁", source_ref="Timeline.md GHC-01")
# ---- BL-02 ----
events["BL-02_0"] = add_event("BL-02",
ts("2024-06-23T05:23:00Z"), 0, "component_introduced",
"冰轮二号着陆东方海(核心舱以东112米)", source_ref="Timeline.md BL-02")
# ---- JC-01 (mission only, no components in M1) ----
events["JC-01_0"] = add_event("JC-01",
ts("2024-06-17T08:19:00Z"), 0, "component_introduced",
"金蟾一号部署至LEO 400×400 km(轨道资产,M1不录入组件)",
source_ref="Timeline.md JC-01")
# ---- GHC-02 ----
events["GHC-02_0"] = add_event("GHC-02",
ts("2024-07-01T10:37:00Z"), 0, "connection_established",
"冰轮一号与冰轮二号通过柔性管道完成燃料连接",
source_ref="Timeline.md GHC-02 EVA-1")
# ---- GHC-03 ----
events["GHC-03_0"] = add_event("GHC-03",
ts("2024-08-15T23:51:00Z"), 0, "component_introduced",
"电力模块搭载广寒01模块着陆东方海", source_ref="Timeline.md GHC-03")
events["GHC-03_1"] = add_event("GHC-03",
ts("2024-08-17T00:00:00Z"), 1, "component_installed",
"电力模块存储支架安装至电力模块北部",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-03 EVA-6")
events["GHC-03_2"] = add_event("GHC-03",
ts("2024-08-18T00:00:00Z"), 2, "component_installed",
"核反应堆、ISRU模块、采矿模块、矿石/燃料存储模块安装完成",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-03 EVA-7/8")
events["GHC-03_3"] = add_event("GHC-03",
ts("2024-08-19T00:00:00Z"), 3, "connection_established",
"核心舱南侧与电力模块北部建立结构直连",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-03 EVA-8")
events["GHC-03_4"] = add_event("GHC-03",
ts("2024-08-19T00:00:00Z"), 4, "state_changed",
"核反应堆以15%功率开始运行",
details={"time_precision": "date", "power_percent": 15},
source_ref="Timeline.md GHC-03")
# ---- BL-03 ----
events["BL-03_0"] = add_event("BL-03",
ts("2024-09-23T19:20:00Z"), 0, "component_introduced",
"冰轮三号(首艘Block 2)着陆东方海", source_ref="Timeline.md BL-03")
# ---- GHC-04 ----
events["GHC-04_0"] = add_event("GHC-04",
ts("2024-10-25T00:00:00Z"), 0, "component_installed",
"核燃料存储模块安装至电力模块东部",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-04 EVA-7")
events["GHC-04_1"] = add_event("GHC-04",
ts("2024-10-27T00:00:00Z"), 1, "component_installed",
"离心机模块吊装至电力模块顶部安装位",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-04 EVA-9")
events["GHC-04_2"] = add_event("GHC-04",
ts("2024-10-31T00:00:00Z"), 2, "connection_removed",
"冰轮一号与冰轮二号之间燃料连接断开(为跳跃做准备)",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-04 EVA-13")
events["GHC-04_3"] = add_event("GHC-04",
ts("2024-11-03T00:00:00Z"), 3, "state_changed",
"核反应堆升至100%功率,ISRU全功率运行",
details={"time_precision": "date", "power_percent": 100},
source_ref="Timeline.md GHC-04")
events["GHC-04_4"] = add_event("GHC-04",
ts("2024-11-05T00:00:00Z"), 4, "connection_established",
"冰轮一号接入基地统一燃料/电力网络",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-04 EVA-14")
events["GHC-04_5"] = add_event("GHC-04",
ts("2024-11-06T00:00:00Z"), 5, "connection_established",
"冰轮二号接入基地统一燃料/电力网络",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-04 EVA-15")
events["GHC-04_6"] = add_event("GHC-04",
ts("2024-11-08T00:00:00Z"), 6, "connection_established",
"冰轮三号接入基地统一燃料/电力网络",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-04 EVA-16")
# ---- GHC-05 ----
events["GHC-05_0"] = add_event("GHC-05",
ts("2024-12-14T04:21:00Z"), 0, "component_introduced",
"吴刚二号着陆东方海广寒基地(手动模式)", source_ref="Timeline.md GHC-05")
events["GHC-05_1"] = add_event("GHC-05",
ts("2024-12-23T01:11:00Z"), 1, "component_introduced",
"广寒03模块(温室+居住舱段一号+居住舱段二号+实验舱段)由冰轮三号运抵月面",
source_ref="Timeline.md GHC-05")
events["GHC-05_2"] = add_event("GHC-05",
ts("2024-12-26T00:00:00Z"), 2, "connection_removed",
"核心舱南侧与电力模块北部结构直连断开(为舱段安装腾出三号位)",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-05 EVA-8")
events["GHC-05_3"] = add_event("GHC-05",
ts("2024-12-27T00:00:00Z"), 3, "component_installed",
"温室舱段安装至核心舱四号位(西侧),手动展开至工作构型",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-05 EVA-9")
events["GHC-05_4"] = add_event("GHC-05",
ts("2024-12-28T00:00:00Z"), 4, "component_installed",
"居住舱段一号安装至核心舱三号位(南侧),电力模块经加压走道连接至居住舱段一号远端",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-05 EVA-10")
events["GHC-05_5"] = add_event("GHC-05",
ts("2024-12-29T00:00:00Z"), 5, "component_installed",
"居住舱段二号安装至核心舱一号位(北侧)",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-05 EVA-11")
events["GHC-05_6"] = add_event("GHC-05",
ts("2024-12-30T00:00:00Z"), 6, "component_installed",
"实验舱段安装至核心舱二号位(东侧),启动航电和环控回路",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-05 EVA-12")
events["GHC-05_7"] = add_event("GHC-05",
ts("2024-12-31T00:00:00Z"), 7, "connection_established",
"吴刚二号通过加压走道连接至温室舱段远端接口",
details={"time_precision": "date"}, source_ref="Timeline.md GHC-05 EVA-13")
events["GHC-05_8"] = add_event("GHC-05",
ts("2025-01-02T00:00:00Z"), 8, "state_changed",
"核反应堆功率调整至30%,全基地整合验证完成",
details={"time_precision": "date", "power_percent": 30},
source_ref="Timeline.md GHC-05 EVA-15")
print(f"Events: {len(events)}")
# ============================================================
# PHASE 4: Components
# ============================================================
def add_component(component_key, component_type, introduced_event_key,
metadata=None):
cur.execute("""
INSERT INTO components
(id, base_id, component_key, component_type,
introduced_by_event_id, metadata)
VALUES (gen_random_uuid(), %(base)s, %(key)s, %(typ)s,
%(ev)s, %(meta)s)
ON CONFLICT (base_id, component_key) DO NOTHING
RETURNING id
""", {
"base": base_id, "key": component_key, "typ": component_type,
"ev": events[introduced_event_key],
"meta": json.dumps(metadata) if metadata else None,
})
row = cur.fetchone()
if row:
return row["id"]
cur.execute(
"SELECT id FROM components WHERE base_id = %(base)s AND component_key = %(key)s",
{"base": base_id, "key": component_key})
return cur.fetchone()["id"]
comp = {}
comp["core_cabin"] = add_component("core_cabin", "module", "GHC-01_0",
metadata={"dryMassT": 28.2, "batteryKwh": 50, "dockingNodes": 4})
comp["binglun_1"] = add_component("binglun_1", "vehicle", "BL-01_0",
metadata={"block": 1, "role": "fuel_transport"})
comp["binglun_2"] = add_component("binglun_2", "vehicle", "BL-02_0",
metadata={"block": 1, "role": "fuel_transport"})
comp["power_module_hub"] = add_component("power_module_hub", "node",
"GHC-03_0")
comp["power_storage_rack"] = add_component("power_storage_rack",
"equipment", "GHC-03_1")
comp["nuclear_reactor"] = add_component("nuclear_reactor", "equipment",
"GHC-03_2")
comp["isru_module"] = add_component("isru_module", "equipment",
"GHC-03_2")
comp["mining_module"] = add_component("mining_module", "equipment",
"GHC-03_2")
comp["ore_fuel_storage"] = add_component("ore_fuel_storage",
"equipment", "GHC-03_2")
comp["binglun_3"] = add_component("binglun_3", "vehicle", "BL-03_0",
metadata={"block": 2, "role": "fuel_transport"})
comp["fuel_storage_mod"] = add_component("fuel_storage_mod",
"equipment", "GHC-04_0")
comp["centrifuge_mod"] = add_component("centrifuge_mod", "equipment",
"GHC-04_1")
comp["habitat_1"] = add_component("habitat_1", "module", "GHC-05_1",
metadata={"capacity": 4, "sleepBags": 2})
comp["habitat_2"] = add_component("habitat_2", "module", "GHC-05_1",
metadata={"capacity": 4, "sleepBags": 2})
comp["greenhouse"] = add_component("greenhouse", "module", "GHC-05_1",
metadata={"foldingArms": 4})
comp["lab_module"] = add_component("lab_module", "module", "GHC-05_1",
metadata={"zones": 3})
comp["wugang_2"] = add_component("wugang_2", "vehicle", "GHC-05_0",
metadata={"block": 2, "type": "lunar_lander"})
print(f"Components: {len(comp)}")
# ============================================================
# PHASE 5: Component Versions
# ============================================================
def add_version(component_key, event_key, display_name, **kwargs):
cid = comp[component_key]
cur.execute("""
INSERT INTO component_versions
(id, component_id, display_name, summary, description,
length_m, width_m, height_m, diameter_m, mass_t,
detail_url, properties, valid_from, started_by_event_id)
VALUES (gen_random_uuid(), %(cid)s, %(name)s, %(sum)s, %(desc)s,
%(len)s, %(wid)s, %(hei)s, %(dia)s, %(mass)s,
%(url)s, %(props)s,
(SELECT effective_at FROM mission_events WHERE id = %(ev)s),
%(ev)s)
ON CONFLICT DO NOTHING
""", {
"cid": cid, "name": display_name,
"sum": kwargs.get("summary"), "desc": kwargs.get("description"),
"len": kwargs.get("length_m"), "wid": kwargs.get("width_m"),
"hei": kwargs.get("height_m"), "dia": kwargs.get("diameter_m"),
"mass": kwargs.get("mass_t"), "url": kwargs.get("detail_url"),
"props": json.dumps(kwargs.get("properties")) if kwargs.get("properties") else None,
"ev": events[event_key],
})
add_version("core_cabin", "GHC-01_0", "广寒核心舱",
summary="广寒基地核心中枢,四向安装节点",
description="核心舱本体干重28.2吨,搭载2.5吨维生资源。配备4个标准安装节点和50kWh蓄电池组。",
mass_t=28.2, detail_url="/home/mission/Guanghan_Program/GHC-01")
add_version("binglun_1", "BL-01_0", "冰轮一号",
summary="首艘冰轮着陆器,Block 1,GHC-04后ISRU已关闭,转为专职燃料运输",
detail_url="/home/Spacecraft/Binglun_Lander")
add_version("binglun_2", "BL-02_0", "冰轮二号",
summary="第二艘冰轮着陆器,Block 1,专职燃料运输",
detail_url="/home/Spacecraft/Binglun_Lander")
add_version("power_module_hub", "GHC-03_0", "电力模块安装节点",
summary="十字型四向安装节点,电力模块中枢",
description="电力模块是独立十字结构,中心为四向安装节点。北部连接存储支架和加压走道模块,南部连接核反应堆,东部连接核燃料存储模块和离心机模块,西部连接ISRU、采矿模块和矿石/燃料存储模块。四个方向顶部各安装一组大型折叠散热面板。")
add_version("power_storage_rack", "GHC-03_1", "电力模块存储支架")
add_version("nuclear_reactor", "GHC-03_2", "核反应堆",
summary="广寒基地主电力来源,GHC-05后以30%功率运行",
properties={"powerPercent": 30})
add_version("isru_module", "GHC-03_2", "ISRU 模块",
summary="基地级原位资源利用设备,负责氢氧燃料生产")
add_version("mining_module", "GHC-03_2", "采矿模块",
summary="月面矿石采集设备,含采矿车和传送系统")
add_version("ore_fuel_storage", "GHC-03_2", "矿石/燃料存储模块",
summary="矿石原料和成品氢氧燃料的存储设施")
add_version("binglun_3", "BL-03_0", "冰轮三号",
summary="首艘Block 2冰轮着陆器,加宽燃料罐,接口与Block 1完全兼容",
detail_url="/home/Spacecraft/Binglun_Lander")
add_version("fuel_storage_mod", "GHC-04_0", "核燃料存储模块",
summary="核反应堆燃料组件存储及废料暂存")
add_version("centrifuge_mod", "GHC-04_1", "离心机模块",
summary="科学实验离心机,安装于电力模块顶部")
add_version("habitat_1", "GHC-05_4", "居住舱段一号",
summary="核心舱三号位(南侧),4铺位+2睡袋,远端连接电力模块",
description="运输构型高2.7m、长6.2m、宽5.0m12.2吨)。展开后高3.2m、长6.2m、宽7.6m,含4个折叠铺位和2个睡袋挂点。",
length_m=6.2, width_m=7.6, height_m=3.2, mass_t=12.2,
properties={"capacity": 4, "sleepBags": 2,
"transportHeightM": 2.7, "transportLengthM": 6.2,
"transportWidthM": 5.0})
add_version("habitat_2", "GHC-05_5", "居住舱段二号",
summary="核心舱一号位(北侧),4铺位+2睡袋",
description="运输构型与居住舱段一号相同。展开后高3.2m、长6.2m、宽7.6m。展开过程中西侧折叠臂曾出现短暂卡滞,手动辅助释放后正常。",
length_m=6.2, width_m=7.6, height_m=3.2, mass_t=12.2,
properties={"capacity": 4, "sleepBags": 2})
add_version("greenhouse", "GHC-05_3", "温室舱段",
summary="核心舱四号位(西侧),4组折叠臂展开的透明面板,远端连接吴刚二号",
description="运输构型高2.8m、长8.7m、宽5.0m(13.5吨)。手动展开折叠框架后达到工作构型高3.2m、长8.7m、宽7.4m。配备自动灌溉系统和温度传感器。",
length_m=8.7, width_m=7.4, height_m=3.2, mass_t=13.5,
properties={"foldingArms": 4,
"transportHeightM": 2.8, "transportLengthM": 8.7,
"transportWidthM": 5.0})
add_version("lab_module", "GHC-05_6", "实验舱段",
summary="核心舱二号位(东侧),3个可调温区,四个舱段中质量最大",
description="运输构型高2.7m、长7.5m、宽5.0m14.2吨)。展开后高3.2m、长7.5m、宽7.5m。含生物培养、材料科学、地质分析三个独立温区。",
length_m=7.5, width_m=7.5, height_m=3.2, mass_t=14.2,
properties={"zones": 3, "zoneNames": ["生物培养", "材料科学", "地质分析"],
"transportHeightM": 2.7, "transportLengthM": 7.5,
"transportWidthM": 5.0})
add_version("wugang_2", "GHC-05_0", "吴刚二号",
summary="首艘Block 2吴刚月面着陆器,GHC-05乘组搭乘抵达,高度雷达故障后手动着陆",
detail_url="/home/Spacecraft/Wugang_Lunar_Lander",
properties={"block": 2, "landingMode": "manual"})
print("Versions created")
# ============================================================
# PHASE 6: Ports
# ============================================================
def add_port(component_key, port_key, display_name, direction=None,
interface_type="structural"):
cur.execute("""
INSERT INTO ports (id, component_id, port_key, display_name,
direction, interface_type)
VALUES (gen_random_uuid(), %(cid)s, %(pkey)s, %(dname)s,
%(dir)s, %(iface)s)
ON CONFLICT (component_id, port_key) DO NOTHING
""", {
"cid": comp[component_key], "pkey": port_key,
"dname": display_name, "dir": direction, "iface": interface_type,
})
# Core cabin: 4 docking nodes
for d, name in [("north", "一号位(北)"), ("east", "二号位(东)"),
("south", "三号位(南)"), ("west", "四号位(西)")]:
add_port("core_cabin", d, name, d)
# Power module hub: 4 directional nodes
for d in ["north", "east", "south", "west"]:
add_port("power_module_hub", d, f"{'北东南西'['north east south west'.split().index(d)]}部安装口", d)
# Power sub-equipment
for key in ["power_storage_rack", "nuclear_reactor", "isru_module",
"mining_module", "ore_fuel_storage", "fuel_storage_mod",
"centrifuge_mod"]:
add_port(key, "mount", "安装接口")
# Habitat modules: core-side + distal
add_port("habitat_1", "core", "核心端接口", "north")
add_port("habitat_1", "distal", "远端对接口", "south")
add_port("habitat_2", "core", "核心端接口", "south")
# Greenhouse: core-side + distal
add_port("greenhouse", "core", "核心端接口", "east")
add_port("greenhouse", "distal", "远端对接口", "west")
# Lab: core-side only
add_port("lab_module", "core", "核心端接口", "west")
# Wugang #2
add_port("wugang_2", "dock", "对接口", interface_type="docking")
# Bingluns: fuel and power ports
for bl in ["binglun_1", "binglun_2", "binglun_3"]:
add_port(bl, "fuel_port", "燃料接口", interface_type="fuel")
add_port(bl, "power_port", "供电接口", interface_type="power")
print("Ports created")
# ============================================================
# PHASE 7: Connections
# ============================================================
def add_connection(comp_a, port_a, comp_b, port_b, conn_type,
event_key, valid_to_event=None):
cur.execute(
"SELECT id FROM ports WHERE component_id = %(cid)s AND port_key = %(pkey)s",
{"cid": comp[comp_a], "pkey": port_a})
pa = cur.fetchone()
cur.execute(
"SELECT id FROM ports WHERE component_id = %(cid)s AND port_key = %(pkey)s",
{"cid": comp[comp_b], "pkey": port_b})
pb = cur.fetchone()
if not pa or not pb:
print(f" WARN: port not found for {comp_a}.{port_a} <-> {comp_b}.{port_b}")
return
cur.execute(
"SELECT effective_at FROM mission_events WHERE id = %(ev)s",
{"ev": events[event_key]})
valid_from = cur.fetchone()["effective_at"]
valid_to = None
ended_by_id = None
if valid_to_event:
cur.execute(
"SELECT effective_at, id FROM mission_events WHERE id = %(ev)s",
{"ev": events[valid_to_event]})
row = cur.fetchone()
if row:
valid_to = row["effective_at"]
ended_by_id = row["id"]
cur.execute("""
INSERT INTO topology_connections
(id, base_id, port_a_id, port_b_id, connection_type,
valid_from, valid_to, established_by_event_id,
ended_by_event_id)
VALUES (gen_random_uuid(), %(base)s, %(pa)s, %(pb)s, %(ct)s,
%(vf)s, %(vt)s, %(ev)s, %(end_ev)s)
ON CONFLICT DO NOTHING
""", {
"base": base_id, "pa": pa["id"], "pb": pb["id"],
"ct": conn_type, "vf": valid_from, "vt": valid_to,
"ev": events[event_key], "end_ev": ended_by_id,
})
# GHC-02: Binglun #1 <-> #2 historical fuel connection
add_connection("binglun_1", "fuel_port", "binglun_2", "fuel_port",
"fuel", "GHC-02_0", valid_to_event="GHC-04_2")
# GHC-03: Core <-> Power (historical, removed in GHC-05)
add_connection("core_cabin", "south", "power_module_hub", "north",
"structural_mount", "GHC-03_3",
valid_to_event="GHC-05_2")
# GHC-03: Power sub-module connections
add_connection("power_module_hub", "north", "power_storage_rack",
"mount", "structural_mount", "GHC-03_1")
add_connection("power_module_hub", "south", "nuclear_reactor",
"mount", "structural_mount", "GHC-03_2")
add_connection("power_module_hub", "west", "isru_module",
"mount", "structural_mount", "GHC-03_2")
add_connection("power_module_hub", "west", "mining_module",
"mount", "structural_mount", "GHC-03_2")
add_connection("power_module_hub", "west", "ore_fuel_storage",
"mount", "structural_mount", "GHC-03_2")
# GHC-04: Power east-side equipment
add_connection("power_module_hub", "east", "fuel_storage_mod",
"mount", "structural_mount", "GHC-04_0")
add_connection("power_module_hub", "east", "centrifuge_mod",
"mount", "structural_mount", "GHC-04_1")
# GHC-04: Binglun fuel & power network
bl_events = {"binglun_1": "GHC-04_4", "binglun_2": "GHC-04_5",
"binglun_3": "GHC-04_6"}
for bl, ev in bl_events.items():
add_connection(bl, "fuel_port", "power_module_hub", "west",
"fuel", ev)
add_connection(bl, "power_port", "power_module_hub", "west",
"power", ev)
# GHC-05: Core <-> four new modules (structural)
add_connection("core_cabin", "north", "habitat_2", "core",
"structural_mount", "GHC-05_5")
add_connection("core_cabin", "east", "lab_module", "core",
"structural_mount", "GHC-05_6")
add_connection("core_cabin", "south", "habitat_1", "core",
"structural_mount", "GHC-05_4")
add_connection("core_cabin", "west", "greenhouse", "core",
"structural_mount", "GHC-05_3")
# GHC-05: Pressurized passages
add_connection("greenhouse", "distal", "wugang_2", "dock",
"pressurized_passage", "GHC-05_7")
add_connection("habitat_1", "distal", "power_module_hub", "north",
"pressurized_passage", "GHC-05_4")
print("Connections created")
# ============================================================
# PHASE 8: Component States
# ============================================================
def add_state(component_key, state_kind, state_value, event_key,
details=None):
cur.execute("""
INSERT INTO component_states
(id, component_id, state_kind, state_value, details,
valid_from, started_by_event_id)
VALUES (gen_random_uuid(), %(cid)s, %(kind)s, %(val)s,
%(det)s,
(SELECT effective_at FROM mission_events WHERE id = %(ev)s),
%(ev)s)
ON CONFLICT DO NOTHING
""", {"cid": comp[component_key], "kind": state_kind,
"val": state_value,
"det": json.dumps(details) if details else None,
"ev": events[event_key]})
# Lifecycle: installed for all components
lifecycle_pairs = [
("core_cabin", "GHC-01_0"), ("binglun_1", "BL-01_0"),
("binglun_2", "BL-02_0"), ("power_module_hub", "GHC-03_0"),
("power_storage_rack", "GHC-03_1"), ("nuclear_reactor", "GHC-03_2"),
("isru_module", "GHC-03_2"), ("mining_module", "GHC-03_2"),
("ore_fuel_storage", "GHC-03_2"), ("binglun_3", "BL-03_0"),
("fuel_storage_mod", "GHC-04_0"), ("centrifuge_mod", "GHC-04_1"),
("habitat_1", "GHC-05_1"), ("habitat_2", "GHC-05_1"),
("greenhouse", "GHC-05_1"), ("lab_module", "GHC-05_1"),
("wugang_2", "GHC-05_0"),
]
for ck, ev in lifecycle_pairs:
add_state(ck, "lifecycle", "installed", ev)
# Operation: operational
ops_pairs = [
("core_cabin", "GHC-01_0"), ("binglun_1", "BL-01_0"),
("binglun_2", "BL-02_0"), ("binglun_3", "BL-03_0"),
("isru_module", "GHC-03_2"), ("mining_module", "GHC-03_2"),
("wugang_2", "GHC-05_0"),
]
for ck, ev in ops_pairs:
add_state(ck, "operation", "operational", ev)
# Nuclear reactor states: 15% (GHC-03) -> 100% (GHC-04) -> 30% (GHC-05)
add_state("nuclear_reactor", "operation", "operational", "GHC-03_4",
details={"powerPercent": 15})
# Close 15% at GHC-04 full power
cur.execute("""
UPDATE component_states
SET valid_to = (SELECT effective_at FROM mission_events WHERE id = %(ev)s),
ended_by_event_id = %(ev)s
WHERE component_id = %(cid)s
AND state_kind = 'operation'
AND details @> '{\"powerPercent\": 15}'
AND valid_to IS NULL
""", {"ev": events["GHC-04_3"], "cid": comp["nuclear_reactor"]})
# Insert 100%
add_state("nuclear_reactor", "operation", "operational", "GHC-04_3",
details={"powerPercent": 100})
# Close 100% at GHC-05 power adjustment
cur.execute("""
UPDATE component_states
SET valid_to = (SELECT effective_at FROM mission_events WHERE id = %(ev)s),
ended_by_event_id = %(ev)s
WHERE component_id = %(cid)s
AND state_kind = 'operation'
AND details @> '{\"powerPercent\": 100}'
AND valid_to IS NULL
""", {"ev": events["GHC-05_8"], "cid": comp["nuclear_reactor"]})
# Insert 30% (current)
add_state("nuclear_reactor", "operation", "operational", "GHC-05_8",
details={"powerPercent": 30})
print("States created")
print("\nSeed complete!")
print(f" Base: 1")
print(f" Missions: {len(mission_ids)}")
print(f" Events: {len(events)}")
print(f" Components: {len(comp)}")
if __name__ == "__main__":
seed()