Files
aibis-dream/Tools/promote_huoshan_test_saves.py
T

140 lines
4.0 KiB
Python

# -*- coding: utf-8 -*-
"""Promote latest FP_Huoshan1 testsavs into StreamingAssets/TestSaveFiles/Huoshan1."""
from __future__ import annotations
import json
import shutil
from pathlib import Path
TESTSAVS = Path.home() / "AppData/LocalLow/Tin Bird/AllOurBrokenParts/AllOurBrokenParts/testsavs"
DEST = Path("Assets/StreamingAssets/TestSaveFiles/Huoshan1")
CATALOG = Path("Assets/StreamingAssets/TestSaveFiles/catalog.json")
YARN = "FP_Huoshan1"
SCENE = "Scene/HuoShanFixScene"
SECTION_ID = "Huoshan1"
SECTION_TITLE = "Huoshan 1"
# DevJump 菜单展示顺序(叙事流程);内容仍取各 node 最新 snapshot。
NODE_ORDER = [
"开头对话",
"Stage2",
"EmoPlugIn",
"检查情绪",
"Stage3",
"结束Stage2",
"SalePlugIn",
"检查销售模块",
"步进查看模式",
"步进_情绪输入",
"销售转动_语义合成",
"销售转动_语言审查",
"销售模块转动完成",
"销售转动_开始",
"销售转动_异常检测",
"查看子模块",
"查询异常进程",
"处理器单次调节失败",
"旋钮调节",
"Stage4",
"结束Stage3",
"Stage5",
"结束Stage4",
"Stage6",
"结束Stage5",
"SpeakPlugIn",
"检查表达",
"手动释放log",
"LOG1梳理完成",
"LOG2梳理完成",
"LOG疏通全部完成",
"Stage8",
"结束Stage7",
"结束对话",
"Center",
]
def sanitize(name: str) -> str:
bad = '<>:"/\\|?*'
for c in bad:
name = name.replace(c, "_")
name = name.replace(" ", "_")
if len(name) > 48:
name = name[:48]
return name or "no_node"
def ensure_catalog_section() -> None:
catalog = {"sections": []}
if CATALOG.exists():
try:
catalog = json.loads(CATALOG.read_text(encoding="utf-8")) or catalog
except json.JSONDecodeError:
catalog = {"sections": []}
sections = catalog.setdefault("sections", [])
for section in sections:
if section.get("id") == SECTION_ID:
if not section.get("title"):
section["title"] = SECTION_TITLE
break
else:
sections.append({"id": SECTION_ID, "title": SECTION_TITLE})
CATALOG.write_text(json.dumps(catalog, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
def main() -> None:
by_node: dict[str, dict] = {}
for d in TESTSAVS.iterdir():
if not d.is_dir():
continue
meta_path = d / "meta.json"
snap_path = d / "snapshot.json"
if not snap_path.exists() or not meta_path.exists():
continue
meta = json.loads(meta_path.read_text(encoding="utf-8"))
if meta.get("yarnProjectId") != YARN:
continue
if meta.get("sceneName") != SCENE:
continue
node = meta.get("nodeName") or "no_node"
if node == "no_node":
continue
saved_at = meta.get("savedAt") or ""
prev = by_node.get(node)
if prev is None or saved_at >= prev["saved_at"]:
by_node[node] = {
"dir": d,
"node": node,
"saved_at": saved_at,
"so": meta.get("sceneSoName") or "",
}
if DEST.exists():
shutil.rmtree(DEST)
DEST.mkdir(parents=True, exist_ok=True)
order_index = {name: i for i, name in enumerate(NODE_ORDER)}
ordered = sorted(
by_node.values(),
key=lambda x: (order_index.get(x["node"], 10_000), x["saved_at"], x["node"]),
)
print(f"unique nodes: {len(ordered)}")
for i, item in enumerate(ordered, start=1):
folder = f"{i:02d}_{sanitize(item['node'])}"
out = DEST / folder
out.mkdir(parents=True, exist_ok=True)
shutil.copy2(item["dir"] / "snapshot.json", out / "snapshot.json")
shutil.copy2(item["dir"] / "meta.json", out / "meta.json")
print(f"OK {folder} | {item['saved_at']} | so={item['so']} | node={item['node']}")
ensure_catalog_section()
print("catalog preserved/updated")
print("done")
if __name__ == "__main__":
main()