Skip to content

Commit ab6b6e0

Browse files
committed
formula v2 design; optimize tweak; new generate mode in dev
1 parent 0c807b5 commit ab6b6e0

File tree

15 files changed

+3348
-283
lines changed

15 files changed

+3348
-283
lines changed

docs/formulav2.md

Lines changed: 453 additions & 73 deletions
Large diffs are not rendered by default.

public/good/game-data.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

scripts/codedump.py

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,102 @@ def _write_resources_ts(
196196
print(f"Written resources to {path}")
197197

198198

199+
def _to_good_key(english_name: str) -> str:
200+
"""Convert an English display name to a GOOD key (PascalCase, no punctuation).
201+
202+
Examples:
203+
Gladiator's Finale -> GladiatorsFinale
204+
Spirit Locket of Boreas -> SpiritLocketOfBoreas
205+
"The Catch" -> TheCatch
206+
"""
207+
name = english_name.replace('"', "").replace("'", "")
208+
words = re.split(r"[^A-Za-z0-9]+", name)
209+
return "".join(w.capitalize() for w in words if w)
210+
211+
212+
_DEDUPE_PREFIXES = ("traveler_", "manekin_", "manekina_")
213+
214+
215+
def generate_good_keys_json(project_root: str) -> None:
216+
"""Generate public/good/game-data.json with GOOD-format keys and Chinese names."""
217+
game_dir = os.path.join(project_root, "src", "data", "game")
218+
out_path = os.path.join(project_root, "public", "good", "game-data.json")
219+
os.makedirs(os.path.dirname(out_path), exist_ok=True)
220+
221+
# --- Characters ---
222+
chars = []
223+
seen_base: set[str] = set()
224+
for rarity in (5, 4):
225+
with open(os.path.join(game_dir, f"character_{rarity}_en.json"), encoding="utf-8") as f:
226+
en = json.load(f)
227+
with open(os.path.join(game_dir, f"character_{rarity}_zh.json"), encoding="utf-8") as f:
228+
zh = json.load(f)
229+
for key in en:
230+
is_variant = any(key.startswith(p) and key != p.rstrip("_") for p in _DEDUPE_PREFIXES)
231+
base = key.rsplit("_", 1)[0] if is_variant else key
232+
if base in seen_base:
233+
continue
234+
seen_base.add(base)
235+
chars.append(
236+
{
237+
"id": _to_good_key(en[key]["name"]),
238+
"rarity": rarity,
239+
"names": {"zh": zh[key]["name"] if key in zh else en[key]["name"]},
240+
}
241+
)
242+
chars.sort(key=lambda c: c["id"])
243+
244+
# --- Weapons ---
245+
with open(os.path.join(game_dir, "weapon_en.json"), encoding="utf-8") as f:
246+
w_en = json.load(f)
247+
with open(os.path.join(game_dir, "weapon_zh.json"), encoding="utf-8") as f:
248+
w_zh = json.load(f)
249+
with open(os.path.join(game_dir, "weapon_stats.json"), encoding="utf-8") as f:
250+
w_stats = json.load(f)
251+
252+
weapons = []
253+
for key in w_en:
254+
if key not in w_stats or w_stats[key]["rarity"] < 3:
255+
continue
256+
weapons.append(
257+
{
258+
"id": _to_good_key(w_en[key]["name"]),
259+
"rarity": w_stats[key]["rarity"],
260+
"type": w_stats[key]["type"].lower(),
261+
"names": {"zh": w_zh[key]["name"] if key in w_zh else w_en[key]["name"]},
262+
}
263+
)
264+
weapons.sort(key=lambda w: w["id"])
265+
266+
# --- Artifact Sets ---
267+
with open(os.path.join(game_dir, "artifact_en.json"), encoding="utf-8") as f:
268+
a_en = json.load(f)
269+
with open(os.path.join(game_dir, "artifact_zh.json"), encoding="utf-8") as f:
270+
a_zh = json.load(f)
271+
272+
artifact_sets = []
273+
for key in a_en:
274+
rarity = a_en[key].get("rarity")
275+
if rarity is None or rarity < 4:
276+
continue
277+
artifact_sets.append(
278+
{
279+
"id": _to_good_key(a_en[key]["name"]),
280+
"rarity": rarity,
281+
"names": {"zh": a_zh[key]["name"] if key in a_zh else a_en[key]["name"]},
282+
}
283+
)
284+
artifact_sets.sort(key=lambda s: s["id"])
285+
286+
# --- Write ---
287+
result = {"characters": chars, "weapons": weapons, "artifactSets": artifact_sets}
288+
with open(out_path, "w", encoding="utf-8") as f:
289+
json.dump(result, f, ensure_ascii=False, separators=(",", ":"))
290+
291+
print(f"Written {out_path}")
292+
print(f" {len(chars)} characters, {len(weapons)} weapons, {len(artifact_sets)} artifact sets")
293+
294+
199295
def _write_i18n_game_ts(data_dir: str, i18n_data: dict[str, dict[str, Any]]) -> None:
200296
"""Write src/data/i18n-game.ts with names-only for weapons/artifacts."""
201297
path = os.path.join(data_dir, "i18n-game.ts")
@@ -427,6 +523,7 @@ def main():
427523
parser.add_argument("--artifact", action="store_true", help="Update artifact data")
428524
parser.add_argument("--half-set", action="store_true", help="Recompute half sets only")
429525
parser.add_argument("--enka", action="store_true", help="Generate Enka ID maps")
526+
parser.add_argument("--good-keys", action="store_true", help="Generate GOOD-format keys JSON")
430527
parser.add_argument(
431528
"--details",
432529
action="store_true",
@@ -440,7 +537,14 @@ def main():
440537
args = parser.parse_args()
441538

442539
# Default to all if no flags provided
443-
if not (args.character or args.weapon or args.artifact or args.half_set or args.enka):
540+
if not (
541+
args.character
542+
or args.weapon
543+
or args.artifact
544+
or args.half_set
545+
or args.enka
546+
or args.good_keys
547+
):
444548
args.character = True
445549
args.weapon = True
446550
args.artifact = True
@@ -618,6 +722,11 @@ def main():
618722
print("=== [5/5] Enka Map Generation ===")
619723
enka.run()
620724

725+
# 6. GOOD Keys JSON
726+
if args.good_keys:
727+
print("=== GOOD Keys JSON ===")
728+
generate_good_keys_json(project_root)
729+
621730

622731
if __name__ == "__main__":
623732
main()

0 commit comments

Comments
 (0)