Files
ZiPingEightChar/评测/工具/extend_cities.py
T
moxiaonian 1a0eed1999 规则库 3.8.1 + 排盘修复 + 评测体系
- 规则库 3.6→3.8.1(542→548 条):剪枝上锁、R-杂-38 从格临界双轨、
  R-事-10~13 冲刑方向判别、R-禁-23 自造必要条件之禁
- 排盘修复随 3.6.2 已发:港澳时区夏令时双向误拨、晚子时双重换日
- 新增 评测/ 目录(BaziQA 题答分离、判分工具、记分卡、with/without-skill 对照)
  与 scripts/query_rules.py 条款检索;ZIPEC_EVAL 评测额度豁免
- manifest 重建并重新签名;VERSION 保持 3.6.2,不发版不打 tag
2026-10-13 12:34:36 +08:00

96 lines
4.3 KiB
Python
Raw 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.
#!/usr/bin/env python3
"""评测用地点扩展:给技能副本的 data/cities.json 追加境外/模糊地名的代理城市条目。
条目与首次评测(fate_benchmark 工作区)所用完全一致,原样搬来:
- 境外城市按真实 IANA 时区(台北/吉隆坡/新加坡/宫崎/香港/澳门);
- 模糊地名(美国/中国/中国大陆)代理到杭州 120.16E Asia/Shanghai,
对齐官方 UTC+8 简化口径;港澳条目对齐母版修复口径(tzdata 自带
1949–1979 夏令时、无 1986–1991 大陆夏令时)。
用法:
python extend_cities.py [--cities <技能副本 data/cities.json>]
[--scripts <技能副本 scripts 目录>]
[--questions <盲版题目目录>]
追加后批跑校验:--questions 所指各届所有命主的 place 字符串逐一过
resolve_location,全部命中才算通过。默认指向母版自身(scripts/、data/),
评测复测时通常先复制一份技能再对副本执行本脚本,避免改动母版。
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1] # 评测/
SKILL = Path(__file__).resolve().parents[2] # 技能母版根
DEFAULT_QUESTIONS = ROOT / "试题" / "BaziQA-全球算命师大赛" / "questions"
TAIPEI = {"lon": 121.56, "lat": 25.03, "tz": "Asia/Taipei"}
KL = {"lon": 101.69, "lat": 3.14, "tz": "Asia/Kuala_Lumpur"}
SG = {"lon": 103.85, "lat": 1.29, "tz": "Asia/Singapore"}
MIYAZAKI = {"lon": 131.42, "lat": 31.91, "tz": "Asia/Tokyo"}
# 官方口径统一按 UTC+8 处理,美国/中国等模糊地名代理到杭州(120.16E)
HANGZHOU_PROXY = {"lon": 120.16, "lat": 30.29, "tz": "Asia/Shanghai"}
# 港澳对齐母版修复口径:港澳 tzdata 自带 1949–1979 夏令时、无 1986–1991 大陆夏令时
HK = {"lon": 114.17, "lat": 22.32, "tz": "Asia/Hong_Kong"}
MO = {"lon": 113.54, "lat": 22.2, "tz": "Asia/Macau"}
GZ = {"lon": 113.26, "lat": 23.13, "tz": "Asia/Shanghai"}
ST = {"lon": 116.68, "lat": 23.35, "tz": "Asia/Shanghai"}
BJ = {"lon": 116.41, "lat": 39.9, "tz": "Asia/Shanghai"}
EXTRA = {
"台北": TAIPEI, "台湾": TAIPEI, "中国台湾": TAIPEI, "台湾,中国": TAIPEI,
"吉隆坡": KL, "马来西亚": KL,
"新加坡": SG,
"宫崎": MIYAZAKI, "日本": MIYAZAKI, "日本宫崎": MIYAZAKI, "日本宫崎县": MIYAZAKI,
"美国": HANGZHOU_PROXY, "中国": HANGZHOU_PROXY, "中国大陆": HANGZHOU_PROXY,
"中国香港": HK, "香港,中国": HK,
"中国澳门": MO, "澳门,中国": MO,
"广东": GZ, "广东,中国": GZ,
"潮汕": ST, "广东潮汕,中国": ST,
"北京,中国": BJ,
}
def main() -> int:
ap = argparse.ArgumentParser(description="评测用地点扩展(境外/模糊地名 → 代理城市)")
ap.add_argument("--cities", type=Path, default=SKILL / "data" / "cities.json")
ap.add_argument("--scripts", type=Path, default=SKILL / "scripts")
ap.add_argument("--questions", type=Path, default=DEFAULT_QUESTIONS)
a = ap.parse_args()
table = json.loads(a.cities.read_text(encoding="utf-8"))
added = 0
for k, v in EXTRA.items():
if k not in table:
table[k] = v
added += 1
a.cities.write_text(json.dumps(table, ensure_ascii=False, indent=1) + "\n",
encoding="utf-8")
print(f"追加 {added} 条(目标 {len(EXTRA)} 条),总条目 {len(table)}")
# 批跑校验:各届全部命主的 place 逐一解析
sys.path.insert(0, str(a.scripts))
from geo.cities import resolve_location # noqa: E402
ok = fail = 0
for f in sorted(a.questions.glob("contest8_*.json")):
for p in json.loads(f.read_text(encoding="utf-8"))[1:]:
place = p["profile"]["birth"]["place"]
try:
loc = resolve_location(place)
ok += 1
print(f" OK {f.name} {p['person_id']:<40} {place!r} -> "
f"{loc.name} {loc.lon}E {loc.tz}")
except Exception as e: # noqa: BLE001
fail += 1
print(f" FAIL {f.name} {p['person_id']:<40} {place!r}: {e}")
print(f"地点解析: {ok} 成功 / {fail} 失败")
return 1 if fail else 0
if __name__ == "__main__":
sys.exit(main())