#!/usr/bin/env python3
"""Checks Chapter 2: offline-safe, counting table complete, unchecked cells marked, links resolve."""
import re, os, sys
d=os.path.dirname(os.path.abspath(__file__))
t=open(os.path.join(d,'ch02-five-languages.html'),encoding='utf-8').read()
ok=True
def check(n,c):
    global ok
    print(('PASS ' if c else 'FAIL ')+n); ok&=bool(c)
check('no outside resources',not re.search(r'<link\b|<script\b|<img\b|url\(',t))
tbl=t.split('Lesson 1.')[1].split('Lesson 2.')[0]
rows=re.findall(r'<tr><td>(\d+)\. ',tbl)
check('counting table has rows 1..10',rows==[str(i) for i in range(1,11)])
cells=re.findall(r'<tr><td>\d+\. .*?</tr>',tbl)
check('every row has 6 language cells',all(len(re.findall(r'<td',c))==6 for c in cells))
check('Nepali and Tibetan cells carry lang tags and romanization',all('lang="ne"' in c and 'lang="bo"' in c and c.count('class="rom"')==2+('lang="yrl"' in c) for c in cells))
check('Dzongkha cells are blank prompts, not filled in',all(re.search(r'<td lang="dz"><span class="blank">find out',c) for c in cells))
check('Tupi-Guarani: only sourced iepé and mukui filled, rest blank prompts',[c.count('find out') for c in cells]==[1,1]+[2]*8 and 'iep' in cells[0] and 'mukui' in cells[1] and sum('lang="yrl"' in c for c in cells)==2)
sk=t.split('Lesson 4.')[1].split('What comes next')[0]
skrows=re.findall(r'<tr><td>(\d+)</td>(.*?)</tr>',sk,re.S)
check('Sanskrit table has rows 1..10 with 5 cells each',[r[0] for r in skrows]==[str(i) for i in range(1,11)] and all(len(re.findall(r'<td',"<td>"+r[1]))==5 for r in skrows))
check('Panini facts sourced (3,983 sutras, eight chapters, dating uncertain)','3,983' in sk and 'eight chapters' in sk and 'uncertain' in sk)
check('Sanskrit numerals marked to confirm','to confirm with a Sanskrit speaker' in sk)
check('UN box sourced and scoped (A/RES/71/178, 2022-2032, Plan not opened)','A/RES/71/178' in t and '2022&ndash;2032' in t and 'Global Action Plan document itself was not opened' in t)
check('Brazil proposal sourced, not claimed as adopted','Carta de Bel' in t and 'nothing saying the government has adopted' in t)
check('Amondawa box sourced, with the narrower claim and the unchecked Hopi/Pirahã flagged','Amondawa' in t and 'not what the authors say' in t and 'I have not checked them here' in t and 'full paper was not read' in t)
check('Oral-traditions box: consent stated, practice marked as author proposal','Oral traditions' in t and 'speakers decide' in t and 'not drawn from a guideline' in t)
check('Reflection questions present in both languages','Before you go on' in t and 'Antes de seguir' in t and 'whom will you help' in t)
check('Hosts-and-guests box sourced, author observation labelled','Hosts and Guests' in t and 'which is not drawn from those sources' in t and 'it does not address language' in t)
l5=t.split('Lesson 5.')[1].split('What the UN is doing')[0]
r5=re.findall(r'<tr><td>(hot \(temperature\)|hot \(spicy\)|cold)</td>(.*?)</tr>',l5,re.S)
check('Lesson 5 has 3 rows of 6 cells, Tibetan/Dzongkha/Tupi-Guarani blank',len(r5)==3 and all(len(re.findall(r'<td','<td>'+x[1]))==6 and x[1].count('find out')==3 for x in r5))
check('Lesson 5 labels the American-culture point as observation, and words as to confirm','author&rsquo;s observation, not a finding' in l5 and 'no source was read' in l5)
check('Translate box: file naming, translations folder, pull request, disclosure of machine use and speaker review, no guessed cells','ch02-bo.html' in t and 'translations' in t and 'pull request' in t and 'machine translation tool' in t and 'speaker of the language has checked' in t and 'blank is better than a wrong one' in t)
check('Write-in-your-language box: voluntary list, no-contact policy sourced, no seeking out','Write in your language' in t and 'only for people who choose' in t and 'does not try to find them' in t and '115 isolated peoples' in t and 'has confirmed 29' in t and 'leave them alone' in t)
check('Empty-seat paragraph: author principle, sourced protections, decision left to them','A seat held empty' in t and 'Uma cadeira vazia' in t and '2022 Supreme Court' in t and 'theirs to say' in t)
check('History box: not a free choice, origins, episodes, counts differ by counter, sources read','not a free choice' in t and 'Matis' in t and '196 groups' in t and '124 by this count' in t and 'was not opened' in t)
check('no text claims isolation was simply chosen','have chosen not to be in contact' not in t and 'isolation they have chosen' not in t and 'escolheram' not in t)
check('Crossing paragraph: sourced, help described as thin, unsupported claims flagged','Crossing into Brazil' in t and 'about 35' in t and 'help is thin' in t and 'nothing on diamonds' in t and 'armed-forces' in t)
l6=t.split('Lesson 6.')[1].split('What the UN is doing')[0]
r6=re.findall(r'<tr><td>([^<]+)</td><td lang="pt">([^<]+)</td>(.*?)</tr>',l6,re.S)
check('Lesson 6 has 9 phrase rows, 6 cells each, 4 blank columns',len(r6)==9 and all(len(re.findall(r'<td','<td>'+x[0]+'</td><td>'+x[1]+'</td>'+x[2]))==6 and x[2].count('find out')==4 for x in r6))
check('Lesson 6 says phrases unverified, numbers unverified, scene invented, notes primary-care scope','no native review' in l6 and 'did not verify the emergency numbers' in l6 and 'covers primary care only' in l6 and 'invented example' in l6)
check('Teofilo Otoni example: bill, signing reported but number/date unconfirmed, voting project flagged unverified','Te&oacute;filo Otoni' in t and 'PL 123/2025' in t and 'awaited the mayor' in t and 'I could not confirm the number or the date' in t and 'reported, not verified' in t)
check('unchecked Tibetan sentence is marked, not invented','for a Tibetan speaker to write' in t)
check('to-confirm box present','To confirm' in t)
check('Portuguese blocks present','lang="pt"' in t)
for h in re.findall(r'href="([^"#]+)"',t):
    if not h.startswith('http'): check('link '+h,os.path.exists(os.path.join(d,h)))
# controls: a table row missing a language cell, or an outside <link>, must be caught
check('control: short row caught',len(re.findall(r'<td','<tr><td>1. one</td><td>um</td></tr>'))!=6)
check('control: outside link caught',bool(re.search(r'<link\b','<link href=x>')))
sys.exit(0 if ok else 1)
