Files
KSP_project/topology_api/seed/seed_ghc01_to_ghc05.py

649 lines
34 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 diagram_nodes")
cur.execute("DELETE FROM diagram_layouts")
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")
events["BL-01_terminal"] = add_event("BL-01",
ts("2024-05-17T23:01:00Z"), 1, "mission_checkpoint",
"BL-01任务最后记录", 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")
events["GHC-02_terminal"] = add_event("GHC-02",
ts("2024-07-15T03:16:00Z"), 1, "mission_checkpoint",
"GHC-02任务最后记录", source_ref="Timeline.md GHC-02末条记录")
# ---- 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")
events["GHC-03_terminal"] = add_event("GHC-03",
ts("2024-08-30T12:45:00Z"), 5, "mission_checkpoint",
"GHC-03任务最后记录", 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")
events["GHC-04_terminal"] = add_event("GHC-04",
ts("2024-11-20T13:57:00Z"), 7, "mission_checkpoint",
"GHC-04任务最后记录", source_ref="Timeline.md GHC-04末条记录")
# ---- 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")
events["GHC-05_terminal"] = add_event("GHC-05",
ts("2025-01-22T10:52:00Z"), 9, "mission_checkpoint",
"GHC-05任务最后记录", source_ref="Timeline.md GHC-05末条记录")
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 1GHC-04后ISRU已关闭,转为专职燃料运输",
height_m=30.2, mass_t=25.0,
detail_url="/home/Spacecraft/Binglun_Lander")
add_version("binglun_2", "BL-02_0", "冰轮二号",
summary="第二艘冰轮着陆器,Block 1,专职燃料运输",
height_m=30.2, mass_t=25.0,
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完全兼容",
height_m=36.7, mass_t=28.194,
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乘组搭乘抵达,高度雷达故障后手动着陆",
diameter_m=11.2, mass_t=9.64,
detail_url="/home/Spacecraft/Wugang_Lunar_Lander",
properties={"block": 2, "landingMode": "manual",
"fuelTankDiameterM": 4.25})
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", "安装接口")
add_port("power_storage_rack", "passage", "加压走道接口", "north",
interface_type="pressurized")
# 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"}
hub_ports = {"binglun_1": "west", "binglun_2": "south",
"binglun_3": "east"}
for bl, ev in bl_events.items():
hub_port = hub_ports[bl]
add_connection(bl, "fuel_port", "power_module_hub", hub_port,
"fuel", ev)
add_connection(bl, "power_port", "power_module_hub", hub_port,
"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_storage_rack", "passage",
"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()