第 1 卷(人物主线):第 1–3 集 + 人物表
主角线:Guspu Frillyknots / Ral Fastenhatchets / Alath Blottedmine 由线索挖掘器自动选定,按因果链切集,经 5 维度自评闸门(≥12 分)后入库。
This commit is contained in:
+81
-20
@@ -14,26 +14,29 @@ from typing import Any
|
||||
|
||||
from defusedxml.ElementTree import iterparse
|
||||
|
||||
# 事件里指向其他实体的字段 → 指向哪类对象
|
||||
ID_FIELDS: dict[str, str] = {
|
||||
"hfid": "figure",
|
||||
"hist_figure_id": "figure",
|
||||
"slayer_hfid": "figure",
|
||||
"slayer_item_id": "artifact",
|
||||
"target_hfid": "figure",
|
||||
"source_hfid": "figure",
|
||||
"site_id": "site",
|
||||
"site_civ_id": "entity",
|
||||
"entity_id": "entity",
|
||||
"attacker_civ_id": "entity",
|
||||
"defender_civ_id": "entity",
|
||||
"artifact_id": "artifact",
|
||||
"region_id": "region",
|
||||
"feature_layer_id": "region",
|
||||
"deity": "figure",
|
||||
"worshipper_hfid": "figure",
|
||||
"creature_id": "creature",
|
||||
}
|
||||
# 字段分类规则来自对真实史料全部 225 种字段的穷举:
|
||||
# 含 "hfid" 的字段全部指向历史人物(共 40+ 个:hfid / hfid_target / group_1_hfid /
|
||||
# slayer_hfid / snatcher_hfid / seeker_hfid / wounder_hfid / teacher_hfid /
|
||||
# conspirator_hfid ...);而 target_enid、identity_id、master_wcid、slayer_item_id 不是。
|
||||
# 旧版手工维护的字典只列了 4 个人物字段,导致关系信息在素材里被丢掉。
|
||||
_ENTITY_SUFFIXES = ("_entity_id", "_civ_id", "_enid")
|
||||
_REGION_FIELDS = {"region_id", "feature_layer_id", "subregion_id"}
|
||||
|
||||
|
||||
def kind_of(tag: str) -> str | None:
|
||||
"""事件字段名 → 它指向的对象类别(非引用类字段返回 None)。"""
|
||||
t = tag.lower()
|
||||
if "hfid" in t or t == "deity" or t.endswith("_deity"):
|
||||
return "figure"
|
||||
if "artifact" in t:
|
||||
return "artifact"
|
||||
if t == "site_id" or t.endswith("_site_id"):
|
||||
return "site"
|
||||
if t in ("entity_id", "target_enid") or t.endswith(_ENTITY_SUFFIXES):
|
||||
return "entity"
|
||||
if t in _REGION_FIELDS:
|
||||
return "region"
|
||||
return None
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -81,6 +84,36 @@ class Event:
|
||||
vals = self.fields.get(tag)
|
||||
return vals[0] if vals else ""
|
||||
|
||||
def ids_of_kind(self, kind: str) -> list[int]:
|
||||
"""本事件中指向该类对象的全部有效 id(去重、剔除 -1 占位)。"""
|
||||
out: list[int] = []
|
||||
for tag, vals in self.fields.items():
|
||||
if kind_of(tag) != kind:
|
||||
continue
|
||||
for raw in vals:
|
||||
i = _int_or_none(raw)
|
||||
if i is not None and i >= 0 and i not in out:
|
||||
out.append(i)
|
||||
return out
|
||||
|
||||
def figure_ids(self) -> list[int]:
|
||||
return self.ids_of_kind("figure")
|
||||
|
||||
def site_ids(self) -> list[int]:
|
||||
return self.ids_of_kind("site")
|
||||
|
||||
def entity_ids(self) -> list[int]:
|
||||
return self.ids_of_kind("entity")
|
||||
|
||||
def field_kinds(self) -> dict[str, list[int]]:
|
||||
"""{类别: [id, ...]},供渲染与建图使用。"""
|
||||
out: dict[str, list[int]] = {}
|
||||
for kind in ("figure", "site", "entity", "artifact", "region"):
|
||||
ids = self.ids_of_kind(kind)
|
||||
if ids:
|
||||
out[kind] = ids
|
||||
return out
|
||||
|
||||
|
||||
@dataclass
|
||||
class Entity:
|
||||
@@ -138,6 +171,34 @@ class World:
|
||||
st = self.sites.get(sid)
|
||||
return pretty(st.name) if st and st.name else f"Site#{sid}"
|
||||
|
||||
def render_refs(self, event: Event) -> list[str]:
|
||||
"""把一条事件里的引用字段渲染成 ``tag=名字``。
|
||||
|
||||
保留字段名是有意的:slayer_hfid=谁 与 hfid=谁 语义完全不同,
|
||||
丢掉字段名就等于丢掉了“谁对谁做了什么”。
|
||||
负 id(DF 的“无此项”占位)与查不到名字的字段直接跳过。
|
||||
"""
|
||||
out: list[str] = []
|
||||
for tag, vals in event.fields.items():
|
||||
kind = kind_of(tag)
|
||||
if kind is None:
|
||||
continue
|
||||
for raw in vals:
|
||||
i = _int_or_none(raw)
|
||||
if i is None or i < 0:
|
||||
continue
|
||||
if kind == "figure":
|
||||
name = self.figure_name(i)
|
||||
elif kind == "site":
|
||||
name = self.site_name(i)
|
||||
elif kind == "entity":
|
||||
name = self.entity_name(i)
|
||||
else:
|
||||
name = ""
|
||||
if name:
|
||||
out.append(f"{tag}={name}")
|
||||
return out
|
||||
|
||||
def event_years(self) -> tuple[int, int]:
|
||||
years = [e.year for e in self.events if e.year]
|
||||
return (min(years), max(years)) if years else (0, 0)
|
||||
|
||||
Reference in New Issue
Block a user