203 lines
9.8 KiB
Python
203 lines
9.8 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
互动组件类型匹配器
|
||
从剧本中的中文类型名 → cType 英文标识
|
||
"""
|
||
|
||
import json
|
||
|
||
# ============ 中互动组件类型映射(27种) ============
|
||
MID_INTERACTION_TYPES = {
|
||
"对话互动": {"cType": "mid_sentence_dialogue", "bitable": "GH0hbBT0ZavkCesaVQ7c40Zfnub"},
|
||
"对话朗读": {"cType": "mid_dialog_repeat", "bitable": "MuwubKXoSaJe55sO4k9c63VSnmh"},
|
||
"对话表达": {"cType": "mid_dialog_express", "bitable": "IC2kbvgP0aLrj7sfzZicIozZn1e"},
|
||
"对话选读": {"cType": "mid_dialog_select", "bitable": "GsNEbjVVYarWqpsNanTcf8UnnPf"},
|
||
"对话选择": {"cType": "mid_dialog_choose", "bitable": "MsETbgiUAaG8h4sct0ycTOzGnfb"},
|
||
"对话挖空": {"cType": "mid_dialog_fillin", "bitable": "X6nHbUztFaGY5tsSHnKcmeJtnm5"},
|
||
"对话组句": {"cType": "mid_dialog_sentence", "bitable": "OfgZbhomiaYj2psBNhuc7THMnF9"},
|
||
"信息描写": {"cType": "mid_message_trace", "bitable": "Nd8cb0tnKankIHsVgw1caL1Xn3f"},
|
||
"信息拼词": {"cType": "mid_message_spell", "bitable": "X0sPb1KERarvocs4rb3cK35AnFg"},
|
||
"信息组句": {"cType": "mid_message_combine", "bitable": "TXYobOAuaakk6KslHp9caUB7nXa"},
|
||
"信息补词": {"cType": "mid_message_fillin", "bitable": "FxwMb8MJmarcRsso2tQcV8thn5g"},
|
||
"信息填词": {"cType": "mid_message_word", "bitable": "ElRebtQe3aeCyOsRjg6cEniznwg"},
|
||
"信息填句": {"cType": "mid_message_sentence", "bitable": "CNFgbIIszaPWXfsekt7cCZjHnVh"},
|
||
"物品互动": {"cType": "mid_vocab_item", "bitable": "BD9Wbi2l9akojasifEvcJG06n3g"},
|
||
"图片互动": {"cType": "mid_vocab_image", "bitable": "VJ1kb9xp8amX8PskntmcLhjpnQe"},
|
||
"图片单选": {"cType": "mid_image_choose", "bitable": "XyIVbYciraBkoasJtV1c3N5Gnhh"},
|
||
"图片多选": {"cType": "mid_image_multiple", "bitable": "XZo5bwagdau3VvsTDL9cJPrInQd"},
|
||
"图片有序": {"cType": "mid_image_sequence", "bitable": "BZWebQROpagkJ0sxArGcsBjwnCU"},
|
||
"图片拖拽": {"cType": "mid_image_drag", "bitable": "Qqq9bVv19aH6LisRrsVcvf6xnqe"},
|
||
"材料互动": {"cType": "mid_sentence_material", "bitable": "Yd84buD91aGxyqstpXqceftHnvM"},
|
||
"指令互动": {"cType": "mid_vocab_instruction", "bitable": "UorxbVCNYaqpx3sOUdTcF6bUnAh"},
|
||
"挖空互动": {"cType": "mid_grammar_cloze", "bitable": "TaU5baUEEagdlusiWXnc7nrGn5b"},
|
||
"组句互动": {"cType": "mid_grammar_sentence", "bitable": "X5w7bWQXGaWu3dsMEE1c3Tp8nBb"},
|
||
"填词互动": {"cType": "mid_vocab_fillBlank", "bitable": "TtjlbkLFgaDi6hsriHZcHBJnnRH"},
|
||
"语音互动": {"cType": "mid_sentence_voice", "bitable": "Qd2kbHD8has9mys3UhWcJbMznrf"},
|
||
"造句互动": {"cType": "mid_sentence_makeSentence", "bitable": "WfHMbzBYPau6hZsmFD0cBwWuncc"},
|
||
"发音互动": {"cType": "mid_pron_pron", "bitable": "CeH5bO3FhaG5cNsPZ4Xc72axnrb"},
|
||
}
|
||
|
||
# ============ 核心互动组件类型映射(待完善cType) ============
|
||
CORE_INTERACTION_TYPES = {
|
||
"合作阅读": {"cType": "core_reading_order", "bitable_wiki": "H6DJweNkpigCbak2Y5LcTZ8Vnfb"},
|
||
"看图选词": {"cType": "core_reading_imageDrag", "bitable_wiki": "MVo7wugWfimJPIkxhJCcqppFnyf", "db_table": "tblKl9CGmARjpw1O"},
|
||
"口语快答": {"cType": "core_speaking_reply", "bitable_wiki": "TSwcw0nFmi21khkpUndchNMsn6f", "db_table": "tbl4Qg8d45O58Cqf"},
|
||
"口语独白": {"cType": None, "bitable_wiki": "G20HwcF1uideNokLsHWcBs3znvg"},
|
||
"口语妙问": {"cType": "core_speaking_inquiry", "bitable_wiki": "GJUVwNSEkis3EXkrVj0ccbqdn8c", "db_table": "tbl1Q68oopST9Mel"},
|
||
"看图说话": {"cType": "core_speaking_image", "bitable_wiki": "KBOXwzVHfin6ORkKbA3c3eWEnoh", "db_table": "tblvi5HF0uSU2GNo"},
|
||
"口语探讨": {"cType": None, "bitable_wiki": "HoidwhEBWiWjaokQnz0cHbhTn6e"},
|
||
"合作听力": {"cType": "core_listening_order", "bitable_wiki": "FrxtwNRQDizqiikPkATcBzTCnYe", "db_table": "tblBuFU6wVKdBh8B"},
|
||
"听力拖拽": {"cType": "core_listening_drag", "bitable_wiki": "K3QrwQnWqiPBm1krhnNcWDTqnhe", "db_table": "tblOOAsgYoZWsTGJ"},
|
||
"听力选择": {"cType": "core_listening_choose", "bitable_wiki": "Kwrcw6A4jip2sxkdLn4czd1knvf", "db_table": "tblH4xNpAmKJ7gEq"},
|
||
"写作互动": {"cType": None, "bitable_wiki": "DVkcwVr2giswTckcgD0cpHwNnv2"},
|
||
"看图组句": {"cType": "core_writing_imgMakeSentence", "bitable_wiki": "BkmtwUBwMiHd5Ak7VS6ccE9SnHd", "db_table": "tblpILmFc9ec17DY"},
|
||
"看图撰写": {"cType": "core_writing_imgWrite", "bitable_wiki": "KwPHwnaqdiWlvNkDm5fcFreDnQh", "db_table": "tblAMaM3g7500Lmm"},
|
||
"邮件组句": {"cType": "core_writing_questionMakeSentence", "bitable_wiki": "M5oTwUP6wiImC4kVJU8cRYnfnyf", "db_table": "tblhS2nk05UsObPA"},
|
||
"邮件撰写": {"cType": "core_writing_questionWrite", "bitable_wiki": "Brn0wldKYizsLZkBqK6clp1tnKd", "db_table": "tblFWw079OkhVlvk"},
|
||
}
|
||
|
||
|
||
def match_component_type(type_text: str) -> dict:
|
||
"""
|
||
从剧本中的类型文本匹配组件类型。
|
||
|
||
Args:
|
||
type_text: 剧本【类型】列的文本值,如 "对话朗读"、"对话挖空-配图"
|
||
|
||
Returns:
|
||
{
|
||
"category": "mid" | "core", # 中互动 or 核心互动
|
||
"cType": "mid_dialog_repeat", # 英文类型标识
|
||
"type_name": "对话朗读", # 中文基础类型名
|
||
"has_image": False, # 是否为配图变体
|
||
"bitable": "MuwubKXoSaJe55sO4k9c63VSnmh", # 对应多维表格token
|
||
"db_table": "middle_interaction_component", # 目标数据库表
|
||
}
|
||
|
||
Raises:
|
||
ValueError: 未知组件类型
|
||
"""
|
||
text = type_text.strip()
|
||
|
||
# 检查是否有配图后缀("-配图" 或 "+图片")
|
||
has_image = False
|
||
if text.endswith("-配图"):
|
||
has_image = True
|
||
text = text.replace("-配图", "").strip()
|
||
elif text.endswith("+图片"):
|
||
has_image = True
|
||
text = text.replace("+图片", "").strip()
|
||
|
||
# 优先匹配中互动
|
||
if text in MID_INTERACTION_TYPES:
|
||
info = MID_INTERACTION_TYPES[text]
|
||
return {
|
||
"category": "mid",
|
||
"cType": info["cType"],
|
||
"type_name": text,
|
||
"has_image": has_image,
|
||
"bitable": info["bitable"],
|
||
"db_table": "middle_interaction_component",
|
||
}
|
||
|
||
# 再匹配核心互动
|
||
if text in CORE_INTERACTION_TYPES:
|
||
info = CORE_INTERACTION_TYPES[text]
|
||
return {
|
||
"category": "core",
|
||
"cType": info["cType"],
|
||
"type_name": text,
|
||
"has_image": has_image,
|
||
"bitable_wiki": info["bitable_wiki"],
|
||
"db_table": "core_interaction_component",
|
||
}
|
||
|
||
raise ValueError(f"未知组件类型: '{type_text}' (清理后: '{text}')")
|
||
|
||
|
||
def match_all(type_list: list) -> list:
|
||
"""批量匹配,返回结果列表,匹配失败的记录error"""
|
||
results = []
|
||
for t in type_list:
|
||
try:
|
||
result = match_component_type(t)
|
||
result["input"] = t
|
||
results.append(result)
|
||
except ValueError as e:
|
||
results.append({"input": t, "error": str(e)})
|
||
return results
|
||
|
||
|
||
# ============ 完整中英类型对照表 ============
|
||
|
||
def get_type_registry():
|
||
"""
|
||
返回完整的中互动组件中英类型对照表
|
||
|
||
Returns:
|
||
list[dict]: [
|
||
{
|
||
"type_name_cn": "对话朗读",
|
||
"cType": "mid_dialog_repeat",
|
||
"category": "mid",
|
||
"bitable": "MuwubKXoSaJe55sO4k9c63VSnmh",
|
||
"db_table": "middle_interaction_component",
|
||
},
|
||
...
|
||
]
|
||
"""
|
||
registry = []
|
||
for cn_name, info in MID_INTERACTION_TYPES.items():
|
||
registry.append({
|
||
"type_name_cn": cn_name,
|
||
"cType": info["cType"],
|
||
"category": "mid",
|
||
"bitable": info["bitable"],
|
||
"db_table": "middle_interaction_component",
|
||
})
|
||
for cn_name, info in CORE_INTERACTION_TYPES.items():
|
||
registry.append({
|
||
"type_name_cn": cn_name,
|
||
"cType": info.get("cType"),
|
||
"category": "core",
|
||
"bitable_wiki": info.get("bitable_wiki"),
|
||
"db_table": "core_interaction_component",
|
||
})
|
||
return registry
|
||
|
||
|
||
def print_type_registry():
|
||
"""打印完整的中英类型对照表"""
|
||
print(f"{'中文类型名':<10} {'cType':<35} {'类别':<6} {'bitable_token'}")
|
||
print("-" * 90)
|
||
for entry in get_type_registry():
|
||
cat = "中互动" if entry["category"] == "mid" else "核心"
|
||
bt = entry.get("bitable") or entry.get("bitable_wiki") or ""
|
||
print(f"{entry['type_name_cn']:<10} {(entry['cType'] or 'TBD'):<35} {cat:<6} {bt}")
|
||
|
||
|
||
# ============ CLI ============
|
||
if __name__ == "__main__":
|
||
import sys
|
||
if len(sys.argv) > 1:
|
||
# 单个匹配
|
||
result = match_component_type(sys.argv[1])
|
||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||
else:
|
||
# 测试:用剧本样例中的所有类型
|
||
test_types = [
|
||
"对话朗读", "对话挖空", "对话组句", "对话选择", "对话选读",
|
||
"对话朗读-配图", "对话挖空-配图",
|
||
"听力选择", "看图说话",
|
||
"信息描写", "物品互动", "图片互动", "图片单选",
|
||
]
|
||
print("=== 组件类型匹配测试 ===\n")
|
||
results = match_all(test_types)
|
||
for r in results:
|
||
if "error" in r:
|
||
print(f"❌ {r['input']}: {r['error']}")
|
||
else:
|
||
cat = "中互动" if r["category"] == "mid" else "核心互动"
|
||
img = " [配图]" if r["has_image"] else ""
|
||
print(f"✅ {r['input']}{img} → {cat} | {r['cType']}")
|