# -*- coding: utf-8 -*-
"""生成两份泰语练习题 docx（四线格 + 选择/判断/连线/分类/标声调）。"""
from docx import Document
from docx.shared import Pt, Inches, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
from docx.oxml import OxmlElement
from io import BytesIO
from PIL import Image, ImageDraw

FONT_LATIN = 'Tahoma'
FONT_EA = '宋体'

# ---------------- 基础 ----------------
def new_doc():
    doc = Document()
    st = doc.styles['Normal']
    st.font.name = FONT_LATIN
    st.font.size = Pt(11)
    st.element.rPr.rFonts.set(qn('w:eastAsia'), FONT_EA)
    for sec in doc.sections:
        sec.top_margin = Inches(0.7)
        sec.bottom_margin = Inches(0.7)
        sec.left_margin = Inches(0.8)
        sec.right_margin = Inches(0.8)
    return doc

def fmt(run, size=11, bold=False, color=None):
    run.font.name = FONT_LATIN
    run._element.rPr.rFonts.set(qn('w:eastAsia'), FONT_EA)
    run.font.size = Pt(size)
    run.font.bold = bold
    if color:
        run.font.color.rgb = RGBColor(*color)

def title(doc, text):
    p = doc.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    fmt(p.add_run(text), 20, bold=True)

def subtitle(doc, text):
    p = doc.add_paragraph(); p.alignment = WD_ALIGN_PARAGRAPH.CENTER
    fmt(p.add_run(text), 13, color=(0x40, 0x40, 0x40))
    p.paragraph_format.space_after = Pt(6)

def heading(doc, text):
    p = doc.add_paragraph()
    fmt(p.add_run(text), 14, bold=True, color=(0x1F, 0x3B, 0x73))
    p.paragraph_format.space_before = Pt(10)
    p.paragraph_format.space_after = Pt(3)

def para(doc, text, size=11, bold=False, color=None, indent=None, space_after=2):
    p = doc.add_paragraph()
    fmt(p.add_run(text), size, bold, color)
    if indent:
        p.paragraph_format.first_line_indent = Pt(indent)
    p.paragraph_format.space_after = Pt(space_after)
    return p

def thai_line(doc, text, size=18, color=(0, 0, 0), space_after=2):
    p = doc.add_paragraph()
    fmt(p.add_run(text), size, color=color)
    p.paragraph_format.space_after = Pt(space_after)
    return p

# ---------------- 四线格 ----------------
def grid_img(n_boxes, box_w=150, height=185,
             line=(110, 110, 110), base_color=(70, 70, 70), divider=(205, 205, 205)):
    pad = 8
    w = pad * 2 + n_boxes * box_w
    img = Image.new('RGB', (w, height), 'white')
    d = ImageDraw.Draw(img)
    top = int(height * 0.16)   # 顶线（上格顶）
    mid = int(height * 0.40)   # 上格线（辅音主体顶）
    base = int(height * 0.64)  # 基线（辅音压线）
    bot = int(height * 0.92)   # 底线（下格底）
    for y in (top, mid, bot):
        d.line([(pad, y), (w - pad, y)], fill=line, width=3)
    d.line([(pad, base), (w - pad, base)], fill=base_color, width=4)  # 基线加粗
    for i in range(1, n_boxes):
        x = pad + i * box_w
        d.line([(x, top), (x, bot)], fill=divider, width=1)
    buf = BytesIO()
    img.save(buf, 'PNG')
    buf.seek(0)
    return buf

def writing_block(doc, label, model_text, n_boxes):
    para(doc, label, bold=True, space_after=0)
    thai_line(doc, model_text, size=18, space_after=1)
    doc.add_picture(grid_img(n_boxes), width=Inches(6.6))
    para(doc, '', size=4, space_after=4)

# ---------------- 表格（连线 / 分类） ----------------
def no_borders(table):
    tbl = table._tbl
    tblPr = tbl.tblPr
    borders = OxmlElement('w:tblBorders')
    for edge in ('top', 'left', 'bottom', 'right', 'insideH', 'insideV'):
        el = OxmlElement('w:' + edge)
        el.set(qn('w:val'), 'none')
        borders.append(el)
    tblPr.append(borders)

def matching(doc, left, right):
    """连线题：左右两列，无边框，供学生连线。"""
    tbl = doc.add_table(rows=0, cols=2)
    tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
    no_borders(tbl)
    n = max(len(left), len(right))
    for i in range(n):
        row = tbl.add_row()
        lp = row.cells[0].paragraphs[0]
        rp = row.cells[1].paragraphs[0]
        if i < len(left):
            fmt(lp.add_run(left[i]), 12)
        if i < len(right):
            rp.alignment = WD_ALIGN_PARAGRAPH.LEFT
            fmt(rp.add_run(right[i]), 12)
    doc.add_paragraph().paragraph_format.space_after = Pt(2)

def classify_table(doc, col1_title, col2_title, rows=7):
    tbl = doc.add_table(rows=1, cols=2)
    tbl.style = 'Table Grid'
    hdr = tbl.rows[0].cells
    fmt(hdr[0].paragraphs[0].add_run(col1_title), 11, bold=True)
    fmt(hdr[1].paragraphs[0].add_run(col2_title), 11, bold=True)
    for _ in range(rows):
        row = tbl.add_row()
        row.cells[0].paragraphs[0].add_run('　')
        row.cells[1].paragraphs[0].add_run('　')
    doc.add_paragraph().paragraph_format.space_after = Pt(2)

# ---------------- 题目渲染 ----------------
def mc(doc, no, stem, options):
    para(doc, f'{no}. {stem}', space_after=1)
    para(doc, '    ' + '　　'.join(options), space_after=4)

def tf(doc, no, stem):
    para(doc, f'{no}. （　　） {stem}', space_after=4)

def tone_item(doc, no, word, n_syl):
    blanks = '、'.join(['____'] * n_syl)
    para(doc, f'{no}. {word}（{n_syl} 音节）→ {blanks}', space_after=4)

# ================================================================
# 试卷一：中辅音 + 单元音、特殊元音
# ================================================================
doc = new_doc()
title(doc, '泰语练习题（一）')
subtitle(doc, '中辅音 · 单元音 · 特殊元音')

para(doc, '【知识速查】中辅音（อักษรกลาง）共 9 个：', bold=True, space_after=0)
thai_line(doc, 'ก  จ  ฎ  ฏ  ด  ต  บ  ป  อ', size=16)
para(doc, 'กอ ไก่(鸡)  จอ จาน(盘)  ฎอ ชฎา(尖顶冠)  ฏอ ปฏัก(刺棒)  ดอ เด็ก(小孩)  ตอ เต่า(龟)  บอ ใบไม้(叶)  ปอ ปลา(鱼)  ออ อ่าง(缸)', size=10, color=(0x60, 0x60, 0x60), space_after=4)
para(doc, '【知识速查】单元音：长元音 9 个、短元音 9 个；特殊元音：อำ ใอ ไอ เอา ฤ ฤๅ', size=10, color=(0x60, 0x60, 0x60), space_after=8)

heading(doc, '一、书写练习（在四线格中书写：辅音主体写在中间格、压在基线上，声调和上元音写上格，下元音写下格）')

writing_block(doc, '（一）抄写中辅音（9 个）：',
              'ก     จ     ฎ     ฏ     ด     ต     บ     ป     อ', 9)

writing_block(doc, '（二）抄写长元音（9 个）：',
              'อา     อี     อื     อู     เอ     แอ     โอ     ออ     เออ', 9)

writing_block(doc, '（三）抄写短元音（9 个）：',
              'อะ     อิ     อึ     อุ     เอะ     แอะ     โอะ     เอาะ     เออะ', 9)

writing_block(doc, '（四）抄写特殊元音（6 个）：',
              'อำ     ใอ     ไอ     เอา     ฤ     ฤๅ', 6)

heading(doc, '二、选择题（每小题只有一个正确答案）')

mc(doc, 1, '下列哪个是中辅音？', ['A. ข', 'B. ก', 'C. ค', 'D. ส'])
mc(doc, 2, '下列哪个不是中辅音？', ['A. จ', 'B. ด', 'C. ต', 'D. ผ'])
mc(doc, 3, '“อา”属于哪一类？', ['A. 短元音', 'B. 长元音', 'C. 特殊元音', 'D. 辅音'])
mc(doc, 4, '下列哪一组全是长元音？', ['A. อา อี อู', 'B. อะ อิ อุ', 'C. เอะ แอะ โอะ', 'D. อำ ใอ ไอ'])
mc(doc, 5, '下列哪个是特殊元音？', ['A. อา', 'B. เอ', 'C. อำ', 'D. โอ'])
mc(doc, 6, '中辅音一共有几个？', ['A. 7 个', 'B. 8 个', 'C. 9 个', 'D. 11 个'])
mc(doc, 7, '下列哪个与“ต”同属中辅音？', ['A. ข', 'B. ค', 'C. ป', 'D. ผ'])
mc(doc, 8, '下列哪一组全是短元音？', ['A. เอ แอ โอ', 'B. เอะ แอะ โอะ', 'C. อา อี อู', 'D. เออ ออ'])
mc(doc, 9, '“ไอ”与“ใอ”的读音：', ['A. 相同', 'B. 不同', 'C. 前者是元音后者是辅音', 'D. 都是辅音'])
mc(doc, 10, '下列哪个元音读长音？', ['A. อะ', 'B. อิ', 'C. อี', 'D. อุ'])
mc(doc, 11, '下列哪个不是特殊元音？', ['A. อำ', 'B. ใอ', 'C. เอา', 'D. แอ'])
mc(doc, 12, '下列哪个不是普通单元音？', ['A. อะ', 'B. อิ', 'C. อำ', 'D. อุ'])

heading(doc, '三、判断题（对的打“√”，错的打“×”）')

tf(doc, 1, 'ก 是中辅音。')
tf(doc, 2, 'ข 是中辅音。')
tf(doc, 3, 'อำ 是特殊元音。')
tf(doc, 4, 'เอ 是短元音。')
tf(doc, 5, '中辅音一共有 9 个。')
tf(doc, 6, 'อา 是长元音。')
tf(doc, 7, 'ฤ 是特殊元音。')
tf(doc, 8, 'ผ 是中辅音。')
tf(doc, 9, 'เอะ 是长元音。')
tf(doc, 10, 'อ 是中辅音。')
tf(doc, 11, '“ไอ”与“ใอ”读音不同。')
tf(doc, 12, 'เอาะ 是长元音。')

heading(doc, '四、连线题')

para(doc, '（一）把左边的元音连到右边正确的类别：', bold=True, space_after=2)
matching(doc,
         ['① อา', '② อิ', '③ อำ', '④ เอะ', '⑤ เอา', '⑥ อี'],
         ['A. 长元音', 'B. 短元音', 'C. 特殊元音', '', '', ''])

para(doc, '（二）把左边的中辅音连到它对应的名称：', bold=True, space_after=2)
matching(doc,
         ['① ก', '② ด', '③ ต', '④ บ', '⑤ ป', '⑥ อ'],
         ['A. 鸡（ไก่）', 'B. 小孩（เด็ก）', 'C. 龟（เต่า）', 'D. 叶（ใบไม้）', 'E. 鱼（ปลา）', 'F. 缸（อ่าง）'])

heading(doc, '【参考答案】')
para(doc, '一、选择题：1.B  2.D  3.B  4.A  5.C  6.C  7.C  8.B  9.A  10.C  11.D  12.C', size=10, color=(0x80, 0x00, 0x00))
para(doc, '二、判断题：1.√  2.×  3.√  4.×  5.√  6.√  7.√  8.×  9.×  10.√  11.×  12.×', size=10, color=(0x80, 0x00, 0x00))
para(doc, '三、连线题（一）：①-A  ②-B  ③-C  ④-B  ⑤-C  ⑥-A　（二）：①-A  ②-B  ③-C  ④-D  ⑤-E  ⑥-F', size=10, color=(0x80, 0x00, 0x00))

out1 = '/home/mi/.openclaw/workspace/泰语练习题-中辅音-单元音-特殊元音.docx'
doc.save(out1)
print('saved', out1)

# ================================================================
# 试卷二：高辅音 + 孪生低辅音 + 拼读声调
# ================================================================
doc = new_doc()
title(doc, '泰语练习题（二）')
subtitle(doc, '高辅音 · 孪生低辅音 · 拼读声调')

para(doc, '【知识速查】高辅音（อักษรสูง）常用 10 个：', bold=True, space_after=0)
thai_line(doc, 'ข  ฉ  ฐ  ถ  ผ  ฝ  ศ  ษ  ส  ห', size=16)
para(doc, 'ขอ ไข่(蛋)  ฉอ ฉิ่ง(铙钹)  ฐอ ฐาน(台座)  ถอ ถุง(袋)  ผอ ผึ้ง(蜂)  ฝอ ฝา(盖)  ศอ ศาลา(亭)  ษอ ฤๅษี(隐士)  สอ เสือ(虎)  หอ หีบ(箱)（另 ฃ 现已停用）', size=10, color=(0x60, 0x60, 0x60), space_after=4)

para(doc, '【知识速查】孪生低辅音（อักษรต่ำคู่）13 个：', bold=True, space_after=0)
thai_line(doc, 'ค  ฆ  ช  ซ  ฌ  ฑ  ฒ  ท  ธ  พ  ฟ  ภ  ฮ', size=16)
para(doc, 'คอ ควาย(水牛)  ฆอ ระฆัง(钟)  ชอ ช้าง(象)  ซอ โซ่(链)  ฌอ เฌอ(树)  ฑอ มณโฑ(曼多)  ฒอ ผู้เฒ่า(老人)  ทอ ทหาร(士兵)  ธอ ธง(旗)  พอ พาน(盘)  ฟอ ฟัน(齿)  ภอ สำเภา(帆船)  ฮอ นกฮูก(猫头鹰)（另 ฅ 现已停用）', size=10, color=(0x60, 0x60, 0x60), space_after=6)

para(doc, '【声调速查】泰语共 5 个声调：1=平调(สามัญ)  2=低平(เอก)  3=降调(โท)  4=高平(ตรี)  5=升调(จัตวา)。', size=10, color=(0x60, 0x60, 0x60), space_after=0)
para(doc, '高辅音：无调号+活音节→5升调；无调号+死音节→2低平； ่→2低平； ้→3降调； ๊→4高平； ๋→5升调。', size=10, color=(0x60, 0x60, 0x60), space_after=0)
para(doc, '孪生低辅音：无调号+活音节→1平调；无调号+短元音死音节→4高平；无调号+长元音死音节→3降调； ่→3降调； ้→4高平；不能用 ๊、๋。', size=10, color=(0x60, 0x60, 0x60), space_after=8)

heading(doc, '一、书写练习（在四线格中书写）')

writing_block(doc, '（一）抄写高辅音（10 个）：',
              'ข     ฉ     ฐ     ถ     ผ     ฝ     ศ     ษ     ส     ห', 10)

writing_block(doc, '（二）抄写孪生低辅音（13 个）：',
              'ค     ฆ     ช     ซ     ฌ     ฑ     ฒ     ท     ธ     พ     ฟ     ภ     ฮ', 13)

writing_block(doc, '（三）拼读抄写——高辅音 ข 的五个声调：',
              'ขา     ข่า     ข้า     ข๊า     ข๋า', 5)

writing_block(doc, '（四）拼读抄写——孪生低辅音 ค 的声调（无 ๊、๋）：',
              'คา     ค่า     ค้า', 3)

heading(doc, '二、选择题（每小题只有一个正确答案）')

mc(doc, 1, '下列哪个是高辅音？', ['A. ก', 'B. ค', 'C. ข', 'D. บ'])
mc(doc, 2, '下列哪个是孪生低辅音？', ['A. ข', 'B. ค', 'C. ผ', 'D. ส'])
mc(doc, 3, '下列哪一组全是高辅音？', ['A. ข ฉ ถ ผ', 'B. ค ช ท พ', 'C. ก จ ด ต', 'D. ง น ม ย'])
mc(doc, 4, '高辅音“ข”对应的孪生低辅音是？', ['A. ช', 'B. ท', 'C. ค', 'D. พ'])
mc(doc, 5, '泰语一共有几个声调？', ['A. 3 个', 'B. 4 个', 'C. 5 个', 'D. 6 个'])
mc(doc, 6, '高辅音 + 无调号 + 长元音（活音节）读第几声？', ['A. 平调', 'B. 低平', 'C. 降调', 'D. 升调'])
mc(doc, 7, '“ขา”读第几声？', ['A. 平调', 'B. 低平', 'C. 降调', 'D. 升调'])
mc(doc, 8, '孪生低辅音 + “่”（ไม้เอก）读第几声？', ['A. 平调', 'B. 低平', 'C. 降调', 'D. 高平'])
mc(doc, 9, '“คา”读第几声？', ['A. 平调', 'B. 低平', 'C. 降调', 'D. 高平'])
mc(doc, 10, '低辅音不能使用的调号是？', ['A. ่', 'B. ้', 'C. ๊ 和 ๋', 'D. 都能用'])
mc(doc, 11, '“ข่า”读第几声？', ['A. 平调', 'B. 低平', 'C. 降调', 'D. 升调'])
mc(doc, 12, '“ค่า”读第几声？', ['A. 平调', 'B. 低平', 'C. 降调', 'D. 高平'])
mc(doc, 13, '“คัด”读第几声？', ['A. 平调', 'B. 低平', 'C. 降调', 'D. 高平'])
mc(doc, 14, '“คาด”读第几声？', ['A. 平调', 'B. 低平', 'C. 降调', 'D. 高平'])

heading(doc, '三、判断题（对的打“√”，错的打“×”）')

tf(doc, 1, 'ข 是高辅音。')
tf(doc, 2, 'ค 是高辅音。')
tf(doc, 3, '孪生低辅音 ค 与高辅音 ข 读音相同。')
tf(doc, 4, '泰语一共有 5 个声调。')
tf(doc, 5, '高辅音 + 无调号 + 短元音（死音节）读升调。')
tf(doc, 6, '“คา”读平调（第一声）。')
tf(doc, 7, '低辅音可以标 ๊（ไม้ตรี）。')
tf(doc, 8, '“ข้า”读降调（第三声）。')
tf(doc, 9, 'ส 是孪生低辅音。')
tf(doc, 10, '“ค่า”读降调（第三声）。')
tf(doc, 11, '“คัด”读高平（第四声）。')
tf(doc, 12, '“คาด”读降调（第三声）。')

heading(doc, '四、连线题（把高辅音与读音相同的孪生低辅音连起来）')

matching(doc,
         ['① ข', '② ฉ', '③ ถ', '④ ผ', '⑤ ฝ', '⑥ ส', '⑦ ห'],
         ['A. ค', 'B. ช', 'C. ท', 'D. พ', 'E. ฟ', 'F. ซ', 'G. ฮ'])

heading(doc, '五、分类题（把下列字母分别填入正确的类别）')

thai_line(doc, 'ข   ค   ฉ   ช   ถ   ท   ผ   พ   ฝ   ฟ   ส   ซ   ห   ฮ', size=15)
classify_table(doc, '高辅音（อักษรสูง）', '孪生低辅音（อักษรต่ำคู่）', rows=7)

heading(doc, '六、标声调（写出下列词语每个音节的声调：1=平调 2=低平 3=降调 4=高平 5=升调）')

tone_item(doc, 1, 'กาแฟ', 2)
tone_item(doc, 2, 'ผัดไทย', 2)
tone_item(doc, 3, 'ตลาด', 2)
tone_item(doc, 4, 'น้ำปลา', 2)
tone_item(doc, 5, 'ขนม', 2)
tone_item(doc, 6, 'ข้าวสาร', 2)
tone_item(doc, 7, 'มะม่วง', 2)
tone_item(doc, 8, 'อาหาร', 2)
tone_item(doc, 9, 'ทหาร', 2)
tone_item(doc, 10, 'ผักบุ้ง', 2)
tone_item(doc, 11, 'ข้าวผัด', 2)
tone_item(doc, 12, 'ส้มโอ', 2)
tone_item(doc, 13, 'มะละกอ', 3)

heading(doc, '【参考答案】')
para(doc, '一、选择题：1.C  2.B  3.A  4.C  5.C  6.D  7.D  8.C  9.A  10.C  11.B  12.C  13.D  14.C', size=10, color=(0x80, 0x00, 0x00))
para(doc, '二、判断题：1.√  2.×  3.√  4.√  5.×  6.√  7.×  8.√  9.×  10.√  11.√  12.√', size=10, color=(0x80, 0x00, 0x00))
para(doc, '三、连线题：①-A  ②-B  ③-C  ④-D  ⑤-E  ⑥-F  ⑦-G', size=10, color=(0x80, 0x00, 0x00))
para(doc, '四、分类题：高辅音=ข ฉ ถ ผ ฝ ส ห；孪生低辅音=ค ช ท พ ฟ ซ ฮ', size=10, color=(0x80, 0x00, 0x00))
para(doc, '五、标声调：1. 1-1  2. 2-1  3. 2-3  4. 4-1  5. 2-1  6. 3-5  7. 4-3  8. 1-5  9. 4-5  10. 2-4  11. 3-2  12. 3-1  13. 4-4-1', size=10, color=(0x80, 0x00, 0x00))

out2 = '/home/mi/.openclaw/workspace/泰语练习题-高辅音-孪生低辅音-拼读声调.docx'
doc.save(out2)
print('saved', out2)
