Files
Hist/scripts/region_codes.py

317 lines
15 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.
# -*- coding: utf-8 -*-
"""地区编码:把 region 字符串映射成「大洲码 + 国家/地区码 + 方位码」,
用于生成编目号(如 AFETNE = 非洲 / 埃塞俄比亚 / 东北部)。
"""
import json
import math
# region -> (大洲码, 国家/地区码, 现代国名[用于查标注点], 固定方位或 None)
# 大洲码:AF 非洲 AS 亚洲 EU 欧洲 NA 北美 SA 南美 OC 大洋洲 AN 南极 GL 全球/海域
REGION_CC = {
# —— 非洲 ——
"东非 · 肯尼亚": ("AF", "KE", "肯尼亚", None),
"东非 · 埃塞俄比亚": ("AF", "ET", "埃塞俄比亚", None),
"东非 · 坦桑尼亚": ("AF", "TZ", "坦桑尼亚", None),
"北非 · 摩洛哥": ("AF", "MA", "摩洛哥", None),
"古埃及 · 孟菲斯": ("AF", "EG", "埃及", None),
"古埃及 · 阿拜多斯": ("AF", "EG", "埃及", None),
"古埃及 · 吉萨": ("AF", "EG", "埃及", None),
"古埃及 · 阿玛纳": ("AF", "EG", "埃及", None),
"古埃及 · 亚历山大港": ("AF", "EG", "埃及", None),
"北非 · 迦太基": ("AF", "TN", "突尼斯", None),
"葡萄牙 · 休达": ("AF", "MA", "摩洛哥", None),
"埃及 · 苏伊士": ("AF", "EG", "埃及", None),
"南非 · 开普敦": ("AF", "ZA", "南非", None),
"南非 · 比勒陀利亚": ("AF", "ZA", "南非", None),
# —— 亚洲 ——
"东亚 · 中国周口店": ("AS", "CN", "中国", None),
"西亚 · 以色列": ("AS", "IL", "以色列", None),
"西亚 · 伊拉克": ("AS", "IQ", "伊拉克", None),
"日本 · 本州": ("AS", "JP", "日本", None),
"西亚 · 两河流域": ("AS", "IQ", "伊拉克", None),
"南亚 · 印度河谷": ("AS", "PK", "巴基斯坦", None),
"美索不达米亚 · 两河流域": ("AS", "IQ", "伊拉克", None),
"美索不达米亚 · 乌尔": ("AS", "IQ", "伊拉克", None),
"美索不达米亚 · 巴比伦": ("AS", "IQ", "伊拉克", None),
"中国 · 河南安阳": ("AS", "CN", "中国", None),
"古印度 · 恒河流域": ("AS", "IN", "印度", None),
"西亚 · 安纳托利亚": ("AS", "TR", "土耳其", None),
"地中海 · 东岸": ("AS", "LB", "黎巴嫩", None),
"中国 · 咸阳": ("AS", "CN", "中国", None),
"古印度 · 蓝毗尼": ("AS", "NP", "尼泊尔", None),
"中国 · 鲁国曲阜": ("AS", "CN", "中国", None),
"古印度 · 华氏城": ("AS", "IN", "印度", None),
"中国 · 北方边塞": ("AS", "CN", "中国", None),
"中国 · 陕西西安": ("AS", "CN", "中国", None),
"中国 · 陕西汉中": ("AS", "CN", "中国", None),
"中国 · 四川": ("AS", "CN", "中国", None),
"犹太 · 伯利恒": ("AS", "PS", "巴勒斯坦", None),
"中国 · 东汉洛阳": ("AS", "CN", "中国", None),
"拜占庭 · 君士坦丁堡": ("AS", "TR", "土耳其", None),
"阿拉伯半岛 · 麦加": ("AS", "SA", "沙特阿拉伯", None),
"中国 · 建康": ("AS", "CN", "中国", None),
"阿拉伯半岛 · 麦地那": ("AS", "SA", "沙特阿拉伯", None),
"波斯 · 萨珊": ("AS", "IR", "伊朗", None),
"朝鲜半岛 · 百济": ("AS", "KR", "韩国", None),
"中亚 · 怛罗斯": ("AS", "KZ", "哈萨克斯坦", None),
"日本 · 京都": ("AS", "JP", "日本", None),
"中国 · 敦煌": ("AS", "CN", "中国", None),
"中国 · 开封": ("AS", "CN", "中国", None),
"中国 · 北宋": ("AS", "CN", "中国", None),
"柬埔寨 · 吴哥": ("AS", "KH", "柬埔寨", None),
"蒙古高原": ("AS", "MN", "蒙古", None),
"中国 · 大都": ("AS", "CN", "中国", None),
"印度 · 卡利卡特": ("AS", "IN", "印度", None),
"印度 · 帕尼帕特": ("AS", "IN", "印度", None),
"日本 · 江户": ("AS", "JP", "日本", None),
"中国 · 广东虎门": ("AS", "CN", "中国", None),
"中国 · 武昌": ("AS", "CN", "中国", None),
"中国 · 沈阳": ("AS", "CN", "中国", None),
"中国 · 江西": ("AS", "CN", "中国", None),
"日本 · 广岛": ("AS", "JP", "日本", None),
"印度 · 新德里": ("AS", "IN", "印度", None),
"以色列 · 特拉维夫": ("AS", "IL", "以色列", None),
"朝鲜半岛": ("AS", "KP", "朝鲜", None),
"尼泊尔 · 珠峰": ("AS", "NP", "尼泊尔", None),
"印度尼西亚 · 万隆": ("AS", "ID", "印度尼西亚", None),
"苏联 · 拜科努尔": ("AS", "KZ", "哈萨克斯坦", None),
"中国 · 罗布泊": ("AS", "CN", "中国", None),
"美国 · 越南": ("AS", "VN", "越南", None),
"中东 · 埃及叙利亚": ("AS", "EG", "埃及", None),
"伊朗 · 德黑兰": ("AS", "IR", "伊朗", None),
"中国 · 香港": ("AS", "CN", "中国", None),
"中国 · 澳门": ("AS", "CN", "中国", None),
"伊拉克 · 巴格达": ("AS", "IQ", "伊拉克", None),
"中国 · 酒泉": ("AS", "CN", "中国", None),
"中国 · 文昌": ("AS", "CN", "中国", None),
# —— 欧洲 ——
"欧洲 · 德国": ("EU", "DE", "德国", None),
"欧洲 · 奥地利": ("EU", "AT", "奥地利", None),
"欧洲 · 法国": ("EU", "FR", "法国", None),
"不列颠 · 威尔特郡": ("EU", "GB", "英国", None),
"爱琴海 · 克里特岛": ("EU", "GR", "希腊", None),
"古希腊 · 奥林匹亚": ("EU", "GR", "希腊", None),
"罗马帝国 · 罗马": ("EU", "IT", "意大利", None),
"古希腊 · 爱奥尼亚": ("EU", "GR", "希腊", None),
"古希腊 · 雅典": ("EU", "GR", "希腊", None),
"古希腊 · 马拉松": ("EU", "GR", "希腊", None),
"古希腊 · 温泉关": ("EU", "GR", "希腊", None),
"古希腊 · 斯塔基拉": ("EU", "GR", "希腊", None),
"马其顿 · 希腊半岛": ("EU", "GR", "希腊", None),
"古希腊 · 叙拉古": ("EU", "IT", "意大利", None),
"古罗马 · 卡普阿": ("EU", "IT", "意大利", None),
"古罗马 · 庞贝": ("EU", "IT", "意大利", None),
"古罗马 · 米兰": ("EU", "IT", "意大利", None),
"罗马帝国 · 塞萨洛尼基": ("EU", "GR", "希腊", None),
"西罗马 · 拉文纳": ("EU", "IT", "意大利", None),
"伊比利亚 · 直布罗陀": ("EU", "GB", "英国", None),
"法兰克 · 图尔": ("EU", "FR", "法国", None),
"法兰克 · 亚琛": ("EU", "DE", "德国", None),
"法兰克 · 凡尔登": ("EU", "FR", "法国", None),
"英格兰 · 黑斯廷斯": ("EU", "GB", "英国", None),
"意大利 · 博洛尼亚": ("EU", "IT", "意大利", None),
"西欧 · 克莱蒙": ("EU", "FR", "法国", None),
"法国 · 巴黎": ("EU", "FR", "法国", None),
"英格兰 · 兰尼米德": ("EU", "GB", "英国", None),
"意大利 · 佛罗伦萨": ("EU", "IT", "意大利", None),
"欧洲 · 英法": ("EU", "FR", "法国", None),
"欧洲 · 意大利": ("EU", "IT", "意大利", None),
"法国 · 鲁昂": ("EU", "FR", "法国", None),
"德意志 · 美因茨": ("EU", "DE", "德国", None),
"西班牙 · 格拉纳达": ("EU", "ES", "西班牙", None),
"德意志 · 维滕贝格": ("EU", "DE", "德国", None),
"波兰 · 弗龙堡": ("EU", "PL", "波兰", None),
"德意志 · 奥格斯堡": ("EU", "DE", "德国", None),
"英吉利海峡": ("EU", "GB", None, "CH"),
"英国 · 伦敦": ("EU", "GB", "英国", None),
"西班牙 · 马德里": ("EU", "ES", "西班牙", None),
"意大利 · 帕多瓦": ("EU", "IT", "意大利", None),
"欧洲 · 威斯特伐利亚": ("EU", "DE", "德国", None),
"英国 · 剑桥": ("EU", "GB", "英国", None),
"法国 · 凡尔赛": ("EU", "FR", "法国", None),
"瑞典 · 乌普萨拉": ("EU", "SE", "瑞典", None),
"欧洲 · 英格兰": ("EU", "GB", "英国", None),
"英国 · 格拉斯哥": ("EU", "GB", "英国", None),
"英格兰 · 伯克利": ("EU", "GB", "英国", None),
"俄国 · 莫斯科": ("EU", "RU", "俄罗斯", None),
"比利时 · 滑铁卢": ("EU", "BE", "比利时", None),
"英格兰 · 斯托克顿": ("EU", "GB", "英国", None),
"克里米亚 · 塞瓦斯托波尔": ("EU", "UA", "乌克兰", None),
"意大利 · 都灵": ("EU", "IT", "意大利", None),
"瑞典 · 斯德哥尔摩": ("EU", "SE", "瑞典", None),
"俄国 · 圣彼得堡": ("EU", "RU", "俄罗斯", None),
"德国 · 柏林": ("EU", "DE", "德国", None),
"德国 · 曼海姆": ("EU", "DE", "德国", None),
"德国 · 维尔茨堡": ("EU", "DE", "德国", None),
"瑞士 · 伯尔尼": ("EU", "CH", "瑞士", None),
"欧洲 · 萨拉热窝": ("EU", "BA", "波斯尼亚", None),
"欧洲 · 康边": ("EU", "FR", "法国", None),
"瑞士 · 日内瓦": ("EU", "CH", "瑞士", None),
"欧洲 · 波兰": ("EU", "PL", "波兰", None),
"苏联 · 斯大林格勒": ("EU", "RU", "俄罗斯", None),
"法国 · 诺曼底": ("EU", "FR", "法国", None),
"欧洲 · 布鲁塞尔": ("EU", "BE", "比利时", None),
"苏联 · 切尔诺贝利": ("EU", "UA", "乌克兰", None),
"欧洲 · 马斯特里赫特": ("EU", "NL", "荷兰", None),
"苏格兰 · 爱丁堡": ("EU", "GB", "英国", None),
"欧洲 · 法兰克福": ("EU", "DE", "德国", None),
# —— 北美 ——
"中南美 · 墨西哥湾": ("NA", "MX", "墨西哥", None),
"北美 · 普利茅斯": ("NA", "US", "美国", None),
"北美 · 费城": ("NA", "US", "美国", None),
"世界 · 纽约": ("NA", "US", "美国", None),
"海地 · 太子港": ("NA", "HT", "海地", None),
"美国 · 萨姆特堡": ("NA", "US", "美国", None),
"美国 · 葛底斯堡": ("NA", "US", "美国", None),
"美国 · 华盛顿": ("NA", "US", "美国", None),
"美国 · 波士顿": ("NA", "US", "美国", None),
"美国 · 门洛帕克": ("NA", "US", "美国", None),
"美国 · 基蒂霍克": ("NA", "US", "美国", None),
"美国 · 纽约": ("NA", "US", "美国", None),
"美国 · 珍珠港": ("NA", "US", "美国", None),
"美国 · 芝加哥": ("NA", "US", "美国", None),
"美国 · 新墨西哥": ("NA", "US", "美国", None),
"古巴 · 哈瓦那": ("NA", "CU", "古巴", None),
"古巴 · 加勒比": ("NA", "CU", "古巴", None),
"美国 · 洛杉矶": ("NA", "US", "美国", None),
"美国 · 西雅图": ("NA", "US", "美国", None),
"美国 · 库比蒂诺": ("NA", "US", "美国", None),
"美国 · 加利福尼亚": ("NA", "US", "美国", None),
"美国 · 旧金山": ("NA", "US", "美国", None),
"美国 · 卡纳维拉尔角": ("NA", "US", "美国", None),
# —— 南美 ——
"南美 · 秘鲁": ("SA", "PE", "秘鲁", None),
"拉丁美洲 · 委内瑞拉": ("SA", "VE", "委内瑞拉", None),
# —— 大洋洲 ——
"澳大利亚 · 植物学湾": ("OC", "AU", "澳大利亚", None),
# —— 跨区域 / 海域 / 极地 ——
"北欧 · 格陵兰": ("NA", "GL", "格陵兰", None),
"西班牙 → 美洲": ("NA", "ES", None, "AM"),
"大西洋 · 托德西利亚斯": ("GL", "PT", None, "TR"),
"欧洲 → 环球": ("GL", "GL", None, "GB"),
"大西洋": ("GL", "AT", None, "OC"),
"挪威 · 南极": ("AN", "AQ", None, "SP"),
}
# 从 Natural Earth 国家数据读取标注点(按 ISO_A2 编码,用于计算条目在国家内的方位)
COUNTRY_LABEL = {}
try:
with open("public/world-countries.geojson", encoding="utf-8") as _f:
_gj = json.load(_f)
for _ft in _gj.get("features", []):
_p = _ft.get("properties", {})
_iso = _p.get("ISO_A2")
if _iso and _iso != "-99" and _p.get("LABEL_X") is not None and _p.get("LABEL_Y") is not None:
COUNTRY_LABEL[_iso.upper()] = (_p["LABEL_X"], _p["LABEL_Y"])
except Exception as _e:
print(f"警告:读取国家标注点失败,方位将回退为 XX:{_e}")
def _dir(lat, lng, cx, cy):
dlat = lat - cy
dlng = lng - cx
ns = "N" if dlat > 0.5 else ("S" if dlat < -0.5 else "")
ew = "E" if dlng > 0.5 else ("W" if dlng < -0.5 else "")
if not ns and not ew:
return "CE"
if not ns:
return "EA" if ew == "E" else "WE"
if not ew:
return "NO" if ns == "N" else "SO"
return ns + ew
# 条目类型枚举:E 事件/战役 P 人物/政党 T 学说/技术 I 文物/艺术品 B 建筑/奇观
TYPE_OVERRIDE = {
# 化石标本(人 → 文物)
"露西 · 南方古猿": "I",
"杰贝尔依罗智人化石": "I",
# 建筑/奇观(物 → B)
"哥贝克力石阵": "B",
"加泰土丘聚落": "B",
"胡夫金字塔": "B",
"巨石阵": "B",
"乌尔金字形神塔": "B",
"米诺斯宫殿": "B",
"罗马斗兽场": "B",
"雅典卫城 · 帕特农神庙": "B",
"万里长城": "B",
"吴哥窟": "B",
"巴黎圣母院": "B",
"亚历山大图书馆": "B",
"博洛尼亚大学": "B",
"苏伊士运河通航": "B",
# 学说/技术(物 → T)
"赫梯铁器": "T",
"造纸术萌芽": "T",
"毕昇活字印刷": "T",
"古腾堡印刷术": "T",
"伽利略天文望远镜": "T",
"哥白尼日心说": "T",
"林奈分类法": "T",
"门捷列夫元素周期表": "T",
"瓦特改良蒸汽机": "T",
"第一条铁路": "T",
"诺贝尔炸药": "T",
"电话发明": "T",
"爱迪生白炽灯": "T",
"本茨汽车": "T",
"莱特兄弟首飞": "T",
"福特T型车": "T",
"晶体管发明": "T",
"斯普特尼克1号": "T",
"iPhone发布": "T",
# 学说/技术(事 → T)
"蔡伦造纸": "T",
"达尔文《物种起源》": "T",
"牛顿《自然哲学的数学原理》": "T",
"爱因斯坦狭义相对论": "T",
"互联网诞生": "T",
"科赫发现结核杆菌": "T",
"伦琴发现X射线": "T",
"琴纳牛痘接种": "T",
"首例心脏移植": "T",
"克隆羊多利": "T",
}
def classify(name, category):
if name in TYPE_OVERRIDE:
return TYPE_OVERRIDE[name]
if category == "人":
return "P"
if category == "事":
return "E"
return "I" # 物(默认文物/艺术品)
def _time_seg(tn):
age = abs(tn)
if age < 10000:
if tn < 0:
return "BC" + f"{math.ceil(age / 100):02d}"
return "AD" + f"{(tn - 1) // 100 + 1:02d}"
if age < 100000:
return "BCE1"
if age < 1000000:
return "BCE2"
if age < 10000000:
return "BCE3"
return "BCE4"
def make_code(tn, region, lat, lng, idx, name, category):
"""生成编目号,如 E3-AFETNE-I0001。"""
t = _time_seg(tn)
# 地区段:大洲 + 国家/地区 + 方位
cont, iso, zh, fixed = REGION_CC.get(region, ("GL", "XX", None, "XX"))
if fixed:
sub = fixed
elif iso.upper() in COUNTRY_LABEL:
cx, cy = COUNTRY_LABEL[iso.upper()]
sub = _dir(lat, lng, cx, cy)
else:
sub = "XX"
prefix = classify(name, category)
return f"{t}-{cont}{iso}{sub}-{prefix}{idx:04d}"