#!/usr/bin/env python3
"""
Monday Generator - Word Parts & Meaning Phase (Learn It, 4 pages)
Used for Weeks 9+: Prefixes, Suffixes, Homophones, Word Meaning
Activities redesigned for morphology instead of phonics patterns.
Usage:
from monday_wp import generate_monday
generate_monday(week_dir=..., week_num=..., topic_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
from weasyprint import HTML
def generate_monday(**kw):
week_dir = kw["week_dir"]
week_num = kw["week_num"]
day_name = kw.get("day_name", "Monday")
topic_label = kw["topic_label"]
words = kw["words"] # (full_word, breakdown, definition) e.g. ("unhappy", "un + happy", "not happy")
learning_text = kw["learning_text"]
prefix_examples = kw["prefix_examples"] # List of formatted example strings
grammar_note = kw["grammar_note"]
grammar_deep = kw["grammar_deep"]
grammar_practice = kw["grammar_practice"]
story_text = kw["story_text"]
sort_labels = kw["sort_labels"] # e.g. ["un-", "re-", "dis-"]
sort_instruction = kw.get("sort_instruction", "Sort each word under the correct word part.")
sort_title = kw.get("sort_title", "Word Part Sort")
fill_data = kw["fill_data"]
opposite_words = kw["opposite_words"]
sentence_words = kw["sentence_words"]
sentence_instruction = kw.get("sentence_instruction",
"Write a complete sentence using each word. Remember: capital letter and period!")
add_prefix_data = kw.get("add_prefix_data", []) # (base_word, affix, full_word) tuples
# Configurable labels for prefix vs suffix
word_part_type = kw.get("word_part_type", "prefix") # "prefix" or "suffix"
examples_title = kw.get("examples_title", f"{word_part_type.capitalize()} Examples")
add_word_part_title = kw.get("add_word_part_title", f"Add the {word_part_type}")
add_word_part_note = kw.get("add_word_part_note", f"Add the {word_part_type} to the base word to make a new word.")
word_cards_note = kw.get("word_cards_note", f"Read each word. Notice the {word_part_type} and how it changes the meaning.")
grammar_activity_title = kw.get("grammar_activity_title", "Grammar")
grammar_practice_title = kw.get("grammar_practice_title", "Grammar Practice")
grammar_practice_note = kw.get("grammar_practice_note", "Practice the grammar concept with each sentence.")
day_dir = os.path.join(week_dir, "Monday")
os.makedirs(day_dir, exist_ok=True)
WORD_NAMES = [w[0] for w in words]
# Word cards - 3-column grid showing word breakdown
cards = '<table class="word-grid" style="border-spacing:3px;">'
for i in range(0, len(words), 3):
cards += '<tr>'
for j in range(i, min(i+3, len(words))):
full_word, breakdown, defn = words[j]
cards += f'<td><div class="word-card" style="padding:4px 6px;"><div class="word" style="font-size:11px;">{full_word}</div><div style="font-size:9px;color:#FF7043;font-weight:bold;margin:2px 0;">{breakdown}</div><div class="def" style="font-size:8.5px;line-height:1.1;">{defn}</div>{write_line()}</div></td>'
cards += '</tr>'
cards += '</table>'
# Sort - columns for each label
sort_words = list(WORD_NAMES)
random.Random(42).shuffle(sort_words)
wbank = word_bank(sort_words, seed=42)
n_cols = len(sort_labels)
cols = ""
for lab in sort_labels:
lines = "".join(write_line() for _ in range(3))
cols += f'<td style="width:{100//n_cols}%;text-align:center;vertical-align:top;border:1.5px solid #B2DFDB;border-radius:6px;padding:6px;background:#FAFAFA;"><div style="font-weight:bold;font-size:11px;color:#26A69A;margin-bottom:6px;">{lab}</div>{lines}</td>'
sort_html = f'<div class="activity">{wbank}<table style="width:100%;border-collapse:separate;border-spacing:3px;"><tr>{cols}</tr></table></div>'
# Copy practice
copy_items = ""
for word, _, _ in words:
copy_items += f'<div style="display:flex;align-items:center;gap:12px;margin:10px 0;"><span style="font-weight:bold;font-size:24px;min-width:100px;color:#26A69A;line-height:34px;">{word}</span><div style="flex:1;position:relative;height:34px;margin:2px 0;width:100%"><div style="position:absolute;left:0;right:0;top:0;border-top:0.6pt solid rgb(0,0,255)"></div><div style="position:absolute;left:0;right:0;bottom:18px;border-bottom:0.4pt dashed rgb(255,0,0)"></div><div style="position:absolute;left:0;right:0;bottom:0;border-bottom:0.6pt solid rgb(0,0,255)"></div></div></div>'
# Fill blank
fill_answers = [a for _, a in fill_data]
fb_bank = word_bank(fill_answers, seed=210)
fb_items = "".join(fill_blank_with_line(s) for s, _ in fill_data)
# Opposites - 2-column table
opp_mid = (len(opposite_words) + 1) // 2
opp_left = "".join(f'<div style="margin:4px 0;font-size:12px;"><strong style="color:#673ab7;font-size:12px;">{w}</strong><br>{write_line()}</div>' for w in opposite_words[:opp_mid])
opp_right = "".join(f'<div style="margin:4px 0;font-size:12px;"><strong style="color:#673ab7;font-size:12px;">{w}</strong><br>{write_line()}</div>' for w in opposite_words[opp_mid:])
opp_html = f'<table style="width:100%;border-collapse:separate;border-spacing:4px;"><tr>' \
f'<td style="vertical-align;top;width:50%">{opp_left}</td>' \
f'<td style="vertical-align;top;width:50%">{opp_right}</td>' \
f'</tr></table>'
# Sentence writing - 2-column table
sent_mid = (len(sentence_words) + 1) // 2
sent_left = "".join(f'<div style="margin:6px 0;"><span style="font-size:11px;font-weight:bold;color:#26A69A;">{w}:</span>{write_line()}</div>' for w in sentence_words[:sent_mid])
sent_right = "".join(f'<div style="margin:6px 0;"><span style="font-size:11px;font-weight:bold;color:#26A69A;">{w}:</span>{write_line()}</div>' for w in sentence_words[sent_mid:])
sent_html = f'<table style="width:100%;border-collapse:separate;border-spacing:4px;"><tr>' \
f'<td style="vertical-align;top;width:50%">{sent_left}</td>' \
f'<td style="vertical-align;top;width:50%">{sent_right}</td>' \
f'</tr></table>'
# Grammar practice - 2-column table
gp_mid = (len(grammar_practice) + 1) // 2
gp_left = ""
for item in grammar_practice[:gp_mid]:
text = item[0] if isinstance(item, tuple) else item
gp_left += f'<div style="margin:4px 0;font-size:12px;">{text}{write_line()}</div>'
gp_right = ""
for item in grammar_practice[gp_mid:]:
text = item[0] if isinstance(item, tuple) else item
gp_right += f'<div style="margin:4px 0;font-size:12px;">{text}{write_line()}</div>'
gp_html = f'<table style="width:100%;border-collapse:separate;border-spacing:4px;"><tr>' \
f'<td style="vertical-align;top;width:50%">{gp_left}</td>' \
f'<td style="vertical-align;top;width:50%">{gp_right}</td>' \
f'</tr></table>'
# Examples - 2-column table
mid = (len(prefix_examples) + 1) // 2
left = prefix_examples[:mid]
right = prefix_examples[mid:]
pe = '<table style="width:100%;border-collapse:separate;border-spacing:4px;font-size:12px;margin:4px 0 8px 0;"><tr>'
pe += f'<td style="vertical-align:top;padding:4px;"><ul style="margin:0;padding-left:16px;">'
for item in left:
pe += f'<li>{item}</li>'
pe += '</ul></td>'
pe += f'<td style="vertical-align:top;padding:4px;"><ul style="margin:0;padding-left:16px;">'
for item in right:
pe += f'<li>{item}</li>'
pe += '</ul></td></tr></table>'
# Add the prefix/suffix activity
add_prefix_html = ""
if add_prefix_data:
add_items = ""
for base_word, affix, _ in add_prefix_data:
if word_part_type == "suffix":
# Suffix goes AFTER base word: fast + -er
add_items += f'<div style="margin:6px 0;font-size:12px;"><strong style="color:#FF7043;">{base_word}</strong> + <strong style="color:#26A69A;">{affix}</strong> = {write_line()}</div>'
else:
# Prefix goes BEFORE base word: un- + happy
add_items += f'<div style="margin:6px 0;font-size:12px;"><strong style="color:#26A69A;">{affix}</strong> + <strong style="color:#FF7043;">{base_word}</strong> = {write_line()}</div>'
add_prefix_html = f'{sectitle(add_word_part_title)}{secnote(add_word_part_note)}' \
f'<div style="font-size:12px;margin:6px 0;">{add_items}</div>'
safe_label = topic_label.replace(' ', '_')
pdf_name = f"Week0{week_num}_{day_name}_{safe_label}.pdf"
html = f"""<!DOCTYPE html>
<html><head><meta charset="utf-8"><style>{CSS}</style></head><body>
<div>
{header("English Language Arts", f"Week {week_num}, {day_name} -- {topic_label}")}
{sectitle("Here's What We're Learning")}
{secnote(learning_text)}
{sectitle("Word Cards")}
{secnote(word_cards_note)}
<div class="word-grid">{cards}</div>
</div>
{page_break()}
<div>
{sectitle(examples_title)}
{pe}
{sectitle("Spelling Story")}
{secnote("Read the story. Circle each spelling word as you find it.")}
<div class="story-box">{story_text}</div>
{sectitle(grammar_activity_title)}
{secnote(grammar_deep)}
{sectitle(grammar_practice_title)}
{secnote(grammar_practice_note)}
<div style="font-size:12px;margin:6px 0;">
{gp_html}
</div>
{page_break()}
{add_prefix_html}
</div>
<div>
{sectitle(sort_title)}
{secnote(sort_instruction)}
{sort_html}
</div>
{page_break()}
<div>
{sectitle("Copy Practice")}
{secnote("Read each word carefully, then copy it neatly on the line.")}
{copy_items}
</div>
{page_break()}
<div>
{sectitle("Fill in the Blank")}
{secnote("Choose a word from the word bank to complete each sentence.")}
{fb_bank}
{fb_items}
{page_break()}
{sectitle("Opposite Match-Up")}
{secnote("Write the opposite of each word.")}
{opp_html}
{sectitle("Sentence Writing")}
{secnote(sentence_instruction)}
{sent_html}
</div>
</body></html>"""
HTML(string=html).write_pdf(os.path.join(day_dir, pdf_name))
print(f"[ok] Week {week_num} Monday generated")