#!/usr/bin/env python3
"""
Wednesday Generator - Word Work (4 pages)
Usage:
from wednesday import generate_wednesday
generate_wednesday(week_dir=..., week_num=..., phonics_label=..., words=..., ...)
"""
import os, sys, random
sys.path.insert(0, os.path.dirname(__file__))
from helpers import CSS, header, sectitle, secnote, write_line, word_bank, fill_blank_with_line, page_break, remember_box
from weasyprint import HTML
def generate_wednesday(**kw):
week_dir = kw["week_dir"]
week_num = kw["week_num"]
day_name = kw.get("day_name", "Wednesday")
phonics_label = kw["phonics_label"]
words = kw["words"]
learning_text = kw["learning_text"]
learning_skills = kw.get("learning_skills", []) # List of skill description strings
reading_passage = kw.get("reading_passage") or kw.get("reading_text", "")
vocab_question = kw.get("vocab_question") or kw.get("vocab_q", "")
syn_ant_words = kw.get("syn_ant_words") or kw.get("syn_ant", [])
word_web_center = kw.get("word_web_center", "")
word_web_instruction = kw.get("word_web_instruction") or kw.get("word_web_suggestions", "Write 4 words connected to the center word.")
sentence_sort_data = kw.get("sentence_sort_data") or kw.get("sort_data", [])
correct_sentences = kw.get("correct_sentences", [])
fill_data = kw.get("fill_data", [])
context_clue = kw.get("context_clue", "")
context_clue_detective = kw.get("context_clue_detective", []) # [sentence, ...] for unlabeled detective
paragraph_label_data = kw.get("paragraph_label_data", []) # [sentence, ...] for unlabeled
day_dir = os.path.join(week_dir, "Wednesday")
os.makedirs(day_dir, exist_ok=True)
WORD_NAMES = [w[0] for w in words]
# ── Build sections ──
# Learning skills
skills_html = ""
if learning_skills:
skills_html = '<ul style="font-size:12px;margin:4px 0 8px 0;">'
for s in learning_skills:
skills_html += f'<li>{s}</li>'
skills_html += '</ul>'
# Reading passage + vocab question
reading_section = ""
if reading_passage:
reading_section = f"""{sectitle("Reading Passage")}
{secnote("Read the passage carefully. Try to find your spelling words as you read.")}
<div class="story-box">{reading_passage}</div>"""
if vocab_question:
reading_section += f"""{sectitle("Vocabulary Questions")}
{secnote("Answer each question based on the passage.")}"""
# Handle tuple/list of questions or single string
if isinstance(vocab_question, (tuple, list)):
for q in vocab_question:
reading_section += f'<div class="fb-item"><p>{q}</p><div style="font-size:12px;">Answer: _______________</div></div>'
else:
reading_section += f'<div class="fb-item"><p>{vocab_question}</p><div style="font-size:12px;">Answer: _______________</div></div>'
# Synonyms & Antonyms
syn_html = ""
for w in syn_ant_words:
syn_html += f'<div style="display:inline-block;width:30%;margin:4px;padding:6px 8px;background:#E0F2F1;border-radius:6px;border:1.5px solid #80CBC4;break-inside:avoid;"><div style="font-weight:bold;color:#26A69A;font-size:12px;margin-bottom:4px;">{w}</div><div style="font-size:10.5px;">Synonym: _____________</div><div style="font-size:10.5px;">Antonym: _____________</div>{write_line()}</div>'
syn_section = ""
if syn_ant_words:
syn_section = f"""{sectitle("Synonyms & Antonyms")}
{secnote("Think of a word that means the SAME thing and a word that means the OPPOSITE.")}
{syn_html}"""
# Word Web
ww_section = ""
if word_web_center:
ww_html = (f'<div style="text-align:center;margin:8px 0;">'
f'<div style="display:inline-block;padding:8px 16px;background:#26A69A;color:white;border-radius:20px;font-weight:bold;font-size:13px;">'
f'{word_web_center}</div>'
f'<div style="margin-top:12px;">'
f'<table style="width:100%;border-collapse:separate;border-spacing:4px;">'
f'<tr><td style="text-align:center;"><div style="height:36px;border:2px dashed #B2DFDB;border-radius:8px;"></div></td>'
f'<td style="text-align:center;"><div style="height:36px;border:2px dashed #B2DFDB;border-radius:8px;"></div></td>'
f'<td style="text-align:center;"><div style="height:36px;border:2px dashed #B2DFDB;border-radius:8px;"></div></td></tr>'
f'<tr><td style="text-align:center;"><div style="height:36px;border:2px dashed #B2DFDB;border-radius:8px;"></div></td>'
f'<td style="text-align:center;"><div style="height:36px;border:2px dashed #B2DFDB;border-radius:8px;"></div></td>'
f'<td style="text-align:center;"><div style="height:36px;border:2px dashed #B2DFDB;border-radius:8px;"></div></td></tr>'
f'</table></div></div>')
ww_section = f"""{sectitle("Word Web")}
{secnote(word_web_instruction)}
{ww_html}"""
# Sentence Sort
sort_html = ""
for idx, sentence in enumerate(sentence_sort_data, 1):
word_list = sentence.split()
shuffled = list(word_list)
random.Random(42 + idx).shuffle(shuffled)
tags = "".join(f'<span style="display:inline-block;background:#FFF3E0;border:1px solid #FFB74D;padding:2px 8px;margin:2px;border-radius:3px;font-size:11px;">{w}</span>' for w in shuffled)
sort_html += f'<div style="margin:8px 0;padding:6px 8px;background:#FAFAFA;border:1.5px solid #B2DFDB;border-radius:6px;"><div style="font-size:11px;font-weight:bold;color:#FF7043;margin-bottom:4px;">Sentence {idx}:</div><div style="margin-bottom:4px;">{tags}</div><div style="font-size:10px;color:#888;margin-bottom:4px;">Your answer:</div>{write_line()}</div>'
sort_section = ""
if sentence_sort_data:
sort_section = f"""{sectitle("Sentence Sort")}
{secnote("Unscramble the words to form a correct sentence.")}
{sort_html}"""
# Correct the Sentences
correct_html = ""
for s in correct_sentences:
correct_html += f'<div style="margin:6px 0;font-size:12px;"><span style="color:#E53935;text-decoration:line-through;">{s}</span><br>{write_line()}</div>'
correct_section = ""
if correct_sentences:
correct_section = f"""{sectitle("Correct the Sentences")}
{secnote("Each sentence is missing a capital letter or punctuation. Rewrite it correctly.")}
{correct_html}"""
# Fill in the Blank
fill_section = ""
if fill_data:
fill_answers = [a for _, a in fill_data]
# Add 2-3 distractors from the word list not in the answers
distractors = [w for w in WORD_NAMES if w not in fill_answers]
rnd = random.Random(340)
rnd.shuffle(distractors)
num_distractors = min(3, len(distractors))
fb_bank_words = fill_answers + distractors[:num_distractors]
fb_bank = word_bank(fb_bank_words, seed=340)
fb_items = "".join(fill_blank_with_line(s) for s, _ in fill_data)
fill_section = f"""{sectitle("Fill in the Blank")}
{secnote("Choose the correct word from the bank.")}
{fb_bank}
{fb_items}"""
# Context Clue (single)
ctx_section = ""
if context_clue:
ctx_section = f"""{sectitle("Context Clues")}
{secnote("Use the sentence to figure out the word meaning.")}
<div class="fb-item"><p>{context_clue}</p><div style="font-size:12px;">Answer: _______________</div></div>"""
# Context Clue Detective — table format (NEW)
detective_section = ""
if context_clue_detective:
det_rows = ""
for sentence in context_clue_detective:
det_rows += f'<tr><td style="font-size:11px;padding:4px;border-bottom:1px solid #eee;">{sentence}</td><td style="width:150px;padding:4px;border-bottom:1px solid #eee;"><div style="border-bottom:1px solid #999;height:16px;"></div></td></tr>'
detective_section = f"""{sectitle("Context Clue Detective", "coral")}
{secnote("Read each sentence. What type of context clue is being used? Write: Definition, Example, Contrast, or Description.")}
<table style="width:100%;border-collapse:collapse;font-size:11px;margin:8px 0;">
<tr style="background:#FFF3E0;"><th style="padding:4px 8px;border-bottom:2px solid #FFB74D;">Sentence</th><th style="padding:4px 8px;border-bottom:2px solid #FFB74D;text-align:center;">Clue Type</th></tr>
{det_rows}
</table>"""
# Paragraph Label Activity (NEW)
para_label_section = ""
if paragraph_label_data:
para_lines = ""
for sentence in paragraph_label_data:
para_lines += f'<div style="margin:4px 0;font-size:11px;">(___) {sentence}</div>'
para_label_section = f"""{sectitle("Paragraph Parts", "coral")}
{secnote("Label each sentence: T = Topic Sentence, D = Detail, C = Conclusion.")}
<div style="background:#F3E5F5;border:1.5px solid #CE93D8;border-radius:6px;padding:8px 10px;margin:8px 0;">
{para_lines}
</div>"""
pdf_name = f"Week0{week_num}_{day_name}_{phonics_label.replace(' ', '_')}.pdf"
# Build all content sections — let WeasyPrint handle page breaks naturally
html = f"""<!DOCTYPE html>
<html><head><meta charset="utf-8"><style>{CSS}</style></head><body>
{header("English Language Arts", f"Week {week_num}, {day_name} -- Word Work & Application")}
{sectitle("Here's What We're Learning")}
{secnote(learning_text)}
{skills_html}
{reading_section}
{syn_section}
{ww_section}
{sort_section}
{correct_section}
{fill_section}
{ctx_section}
{detective_section}
{para_label_section}
</body></html>"""
HTML(string=html).write_pdf(os.path.join(day_dir, pdf_name))
print(f"[ok] Week {week_num} Wednesday generated")