#!/usr/bin/env python3
"""
Week 1: Numbers 101-110
Phase 1: Number Sense & Operations
Standard: 2.NBT.A.1 — Count to 120; read and write numerals;
represent a number of objects with a written numeral.
New Standard (7 principles):
1. Reduced drill (sequences reduced from 4 to 2 per warm-up)
2. Estimate First boxes (Mon, Fri)
3. Multiple strategies ("Show 108 two different ways", Tue)
4. Better word problems ("Read carefully. Think about what's happening.", Thu)
5. Create Your Own open-ended challenge (Thu)
6. Number Talks — explain WITHOUT calculating (Mon, Tue, Wed)
7. Friday self-check with emoji + "One thing I learned"
"""
import os
import glob
from weasyprint import HTML
from math_helpers import (
CSS, TEACHER_CSS,
page, page_multi, hdr, sec, b, bw, bl,
tg_page, tg_page_multi, tg_sec, tg_note, tg_section_title,
)
BASE = os.path.expanduser("~/Home_School/2nd_Grade/Math")
WEEK = os.path.join(BASE, "Week_1")
# ═══════════════════════════════════════════════════
# MONDAY — Reading & Writing Numbers to 110
# ═══════════════════════════════════════════════════
def monday():
# 1: Warm-up — count on by 1s (REDUCED drill: 2 sequences, not 4)
s1 = '<div class="abox" style="background:#e8f5e9;">'
s1 += '<p><b>Count on by 1s</b> — Fill in the missing numbers.</p>'
s1 += '<div class="mgrid c1">'
s1 += '<div class="abox" style="font-size:17px;">101, 102, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, 105, <u>' + b('3em') + '</u></div>'
s1 += '<div class="abox" style="font-size:17px;">105, 106, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, 110</div>'
s1 += '</div></div>'
# 2: Read number words → write the numeral
s2 = '<p class="note">Read the number word. Write the numeral.</p>'
s2 += '<div class="mgrid c2">'
words = ["one hundred one", "one hundred four", "one hundred eight", "one hundred ten"]
for w in words:
s2 += f'<div class="abox" style="text-align:center; font-size:16px;">{w}<br>= <u>{b("5em")}</u></div>'
s2 += '</div>'
# 3: Write the number word for each numeral
s3 = '<p class="note">Write the number word. (Remember: no "and" — we say "one hundred two.")</p>'
s3 += '<div class="mgrid c1">'
for n in ["102", "106", "109"]:
s3 += f'<div class="abox" style="font-size:16px;">{n} = <u>{bw("16em")}</u></div>'
s3 += '</div>'
# 4: Estimate First!
s4 = '<div class="abox" style="background:#fff3e0;">'
s4 += '<p><b>Estimate First!</b> Think about the number line from 100 to 110. Don\'t count — just picture it!</p>'
s4 += '<div class="mgrid c2">'
s4 += '<div class="abox"><p>Is <b>102</b> closer to 100 or 110?</p><p>' + b('5em') + '</p></div>'
s4 += '<div class="abox"><p>Is <b>109</b> closer to 100 or 110?</p><p>' + b('5em') + '</p></div>'
s4 += '</div></div>'
# 5: Number Talk
s5 = '<div class="abox" style="background:#e3f2fd;">'
s5 += '<p><b>Number Talk</b> — Aria says the number after 109 is <b>110</b>. Ben says it is <b>200</b>. Who is right? Explain WITHOUT counting all the way from 1.</p>'
s5 += '<p style="margin-top:8px;">' + bl('20em') + '</p>'
s5 += '<p style="margin-top:8px;">' + bl('20em') + '</p>'
s5 += '</div>'
return page(1, "Monday", "Reading & Writing Numbers to 110",
f'''{sec(1, "Count On by 1s", s1)}
{sec(2, "Read Number Words", s2)}
{sec(3, "Write Number Words", s3)}
{sec(4, "Estimate First!", s4)}
{sec(5, "Number Talk: What Comes After 109?", s5)}''')
# ═══════════════════════════════════════════════════
# TUESDAY — Place Value: Hundreds, Tens, Ones
# ═══════════════════════════════════════════════════
def tuesday():
# 1: Learn box + guided place-value table
s1 = '<div class="abox" style="background:#e8f5e9;">'
s1 += '<p><b>Learn:</b> 107 = <b>1 hundred</b> + <b>0 tens</b> + <b>7 ones</b>. The 0 in the tens place means "no tens"!</p>'
s1 += '</div>'
s1 += '<p class="note">Write how many hundreds, tens, and ones.</p>'
s1 += '<div class="mgrid c1">'
for n in ["103", "106", "110"]:
s1 += (f'<div class="abox" style="font-size:16px;"><b>{n}</b> = '
+ b('3em') + ' hundreds ' + b('3em') + ' tens ' + b('3em') + ' ones</div>')
s1 += '</div>'
# 2: Build the number from units (2.NBT.A.1 — written numeral from units)
s2 = '<p class="note">Write the number.</p>'
s2 += '<div class="mgrid c2">'
units = [
"1 hundred + 0 tens + 5 ones",
"1 hundred + 0 tens + 9 ones",
"1 hundred + 1 ten + 0 ones",
"1 hundred + 0 tens + 2 ones",
]
for u in units:
s2 += f'<div class="abox" style="font-size:15px;">{u} = <u>{b("5em")}</u></div>'
s2 += '</div>'
# 3: Multiple strategies — show 108 two different ways
s3 = '<div class="abox" style="background:#f3e5f5;">'
s3 += '<p><b>Two Ways!</b> Show the number <b>108</b> two different ways. '
s3 += 'You could draw base-10 blocks, write it as 100 + 8, use tally marks, or your own way!</p>'
s3 += '<div class="mgrid c2">'
s3 += '<div><p style="font-size:12px;"><b>Way 1:</b></p><div class="draw-box" style="min-height:90px;"></div></div>'
s3 += '<div><p style="font-size:12px;"><b>Way 2:</b></p><div class="draw-box" style="min-height:90px;"></div></div>'
s3 += '</div></div>'
# 4: Number Talk
s4 = '<div class="abox" style="background:#e3f2fd;">'
s4 += '<p><b>Number Talk</b> — Look at <b>104</b> and <b>110</b>. Which one has more tens? Explain how you know WITHOUT counting.</p>'
s4 += '<p style="margin-top:8px;">' + bl('20em') + '</p>'
s4 += '<p style="margin-top:8px;">' + bl('20em') + '</p>'
s4 += '</div>'
return page(1, "Tuesday", "Place Value: Hundreds, Tens, Ones",
f'''{sec(1, "Hundreds, Tens, and Ones", s1)}
{sec(2, "Build the Number", s2)}
{sec(3, "Show 108 Two Ways", s3)}
{sec(4, "Number Talk: Who Has More Tens?", s4)}''')
# ═══════════════════════════════════════════════════
# WEDNESDAY — Comparing Numbers
# ═══════════════════════════════════════════════════
def wednesday():
# 1: Compare with <, >, = (REDUCED drill: 5 problems, not 10)
s1 = '<div class="abox" style="background:#e8f5e9;">'
s1 += '<p><b>Learn:</b> The alligator mouth eats the BIGGER number! 103 <b><</b> 108 because 108 is bigger.</p>'
s1 += '</div>'
s1 += '<p class="note">Write <, >, or = in each circle.</p>'
s1 += '<div class="mgrid c2">'
pairs = [("103", "108"), ("110", "101"), ("106", "106"), ("109", "104"), ("102", "107")]
for a, c in pairs:
s1 += (f'<div class="abox" style="text-align:center; font-size:18px;">{a} '
f'<span class="obox" style="min-width:1.8em; min-height:1.6em;"> </span> {c}</div>')
s1 += '</div>'
# 2: Circle the greater number
s2 = '<p class="note">Circle the GREATER number in each pair.</p>'
s2 += '<div class="mgrid c3">'
for a, c in [("105", "102"), ("108", "110"), ("101", "104")]:
s2 += f'<div class="abox" style="text-align:center; font-size:20px;">{a} {c}</div>'
s2 += '</div>'
# 3: True or False
s3 = '<p class="note">Write T (true) or F (false).</p>'
s3 += '<div class="mgrid c2">'
stmts = ["107 > 104", "103 > 109", "110 = 110", "105 < 102"]
for st in stmts:
s3 += f'<div class="abox" style="font-size:17px;">{st} <u>{b("3em")}</u></div>'
s3 += '</div>'
# 4: Number Talk
s4 = '<div class="abox" style="background:#e3f2fd;">'
s4 += '<p><b>Number Talk</b> — Which is larger: <b>110</b> or <b>101</b>? Explain WITHOUT counting. (Hint: look at the tens place!)</p>'
s4 += '<p style="margin-top:8px;">' + bl('20em') + '</p>'
s4 += '<p style="margin-top:8px;">' + bl('20em') + '</p>'
s4 += '</div>'
return page(1, "Wednesday", "Comparing Numbers",
f'''{sec(1, "Compare with <, >, =", s1)}
{sec(2, "Circle the Greater Number", s2)}
{sec(3, "True or False?", s3)}
{sec(4, "Number Talk: 110 or 101?", s4)}''')
# ═══════════════════════════════════════════════════
# THURSDAY — Counting On & Ordering
# ═══════════════════════════════════════════════════
def thursday():
# 1: Count on by 1s and 10s — forward AND backward (2.NBT.A.1: from any number)
s1 = '<p class="note">Fill in the missing numbers.</p>'
s1 += '<div class="mgrid c1">'
s1 += '<div class="abox" style="font-size:16px;">Count by 1s: 98, 99, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u></div>'
s1 += '<div class="abox" style="font-size:16px;">Count by 10s: 80, 90, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u></div>'
s1 += '<div class="abox" style="font-size:16px;">Count BACKWARD by 1s: 110, 109, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, 106</div>'
s1 += '<div class="abox" style="font-size:16px;">Count by 10s: 90, 100, 110, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u></div>'
s1 += '</div>'
# 2: Before and after
s2 = '<p class="note">Write the number that comes BEFORE and AFTER.</p>'
s2 += '<div class="mgrid c3">'
for n in ["105", "102", "109"]:
s2 += (f'<div class="abox" style="text-align:center; font-size:17px;"><u>{b("3em")}</u>, '
f'<b>{n}</b>, <u>{b("3em")}</u></div>')
s2 += '</div>'
# 3: Ordering numbers
s3 = '<p class="note">Write the numbers in order.</p>'
s3 += '<div class="mgrid c1">'
s3 += '<div class="abox" style="font-size:16px;">Least to greatest: 108, 101, 105 → <u>' + b('3.5em') + '</u>, <u>' + b('3.5em') + '</u>, <u>' + b('3.5em') + '</u></div>'
s3 += '<div class="abox" style="font-size:16px;">Least to greatest: 110, 102, 107, 104 → <u>' + b('3.5em') + '</u>, <u>' + b('3.5em') + '</u>, <u>' + b('3.5em') + '</u>, <u>' + b('3.5em') + '</u></div>'
s3 += '<div class="abox" style="font-size:16px;">Greatest to least: 103, 109, 106 → <u>' + b('3.5em') + '</u>, <u>' + b('3.5em') + '</u>, <u>' + b('3.5em') + '</u></div>'
s3 += '</div>'
# 4: Better word problems
s4 = '<div class="wp">'
s4 += '<p class="note">Read carefully. Think about what\'s happening in the story.</p>'
s4 += '<div class="mgrid c1">'
s4 += ('<div class="abox"><p>Maya\'s book has 110 pages. She is on page 104. '
'Tonight she reads 1 more page. What page is she on now?</p>'
'<p style="margin-top:6px;">Answer: ' + b('5em') + '</p></div>')
s4 += ('<div class="abox"><p>The gym can hold 110 kids. There are 101 kids inside. '
'Can 10 MORE kids come in? Explain your thinking.</p>'
'<p style="margin-top:6px;">Yes / No: ' + b('4em') + ' Because: ' + bw('14em') + '</p></div>')
s4 += '</div></div>'
# 5: Create Your Own
s5 = '<div class="starbox">'
s5 += '<p><b>Create Your Own!</b> Write your own comparing problem. Pick two numbers between 101 and 110. Ask someone in your family to solve it!</p>'
s5 += '<p style="margin-top:8px;">My problem: ' + bl('18em') + '</p>'
s5 += '<p style="margin-top:8px;">The answer: ' + bw('12em') + '</p>'
s5 += '</div>'
return page(1, "Thursday", "Counting On & Ordering Numbers",
f'''{sec(1, "Count On (Forward and Backward)", s1)}
{sec(2, "Before and After", s2)}
{sec(3, "Put Them in Order", s3)}
{sec(4, "Word Problems", s4)}
{sec(5, "Create Your Own", s5)}''')
# ═══════════════════════════════════════════════════
# FRIDAY — Review & Self-Check
# ═══════════════════════════════════════════════════
def friday():
# 1: Estimate First
s1 = '<div class="abox" style="background:#fff3e0;">'
s1 += '<p><b>Estimate First!</b> Picture the number line from 100 to 110. Don\'t count!</p>'
s1 += '<div class="mgrid c2">'
s1 += '<div class="abox"><p>Is <b>106</b> closer to 100 or 110?</p><p>' + b('5em') + '</p></div>'
s1 += '<div class="abox"><p>Is <b>101</b> closer to 100 or 110?</p><p>' + b('5em') + '</p></div>'
s1 += '</div></div>'
# 2: Mixed review (REDUCED: 6 problems covering all week's skills)
s2 = '<p class="note">Show what you know!</p>'
s2 += '<div class="mgrid c2">'
s2 += '<div class="abox"><p>Write the numeral: one hundred three</p><p><u>' + b('5em') + '</u></p></div>'
s2 += '<div class="abox"><p>Write the number word for 110:</p><p><u>' + bw('14em') + '</u></p></div>'
s2 += '<div class="abox"><p>1 hundred + 0 tens + 4 ones = <u>' + b('5em') + '</u></p></div>'
s2 += '<div class="abox"><p>Compare: 102 <span class="obox" style="min-width:1.8em; min-height:1.6em;"> </span> 108</p></div>'
s2 += '<div class="abox"><p>What comes AFTER 106? <u>' + b('4em') + '</u></p></div>'
s2 += '<div class="abox"><p>What comes BEFORE 105? <u>' + b('4em') + '</u></p></div>'
s2 += '</div>'
# 3: Count and order
s3 = '<p class="note">Fill in the blanks, then put the numbers in order.</p>'
s3 += '<div class="mgrid c1">'
s3 += '<div class="abox" style="font-size:16px;">106, 107, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, 110</div>'
s3 += '<div class="abox" style="font-size:16px;">Least to greatest: 109, 103, 110 → <u>' + b('3.5em') + '</u>, <u>' + b('3.5em') + '</u>, <u>' + b('3.5em') + '</u></div>'
s3 += '</div>'
# 4: Self-check with reflection
s4 = '<div class="selfcheck">'
s4 += '<p><b>Self-Check: How do you feel about numbers 101-110?</b></p>'
s4 += '<div style="display:flex; gap:16px; flex-wrap:wrap;">'
topics = [("Reading & Writing to 110", "#fff3e0"),
("Hundreds, Tens, Ones", "#e8f5e9"),
("Comparing & Ordering", "#e3f2fd")]
for t, bg in topics:
s4 += f'<div style="background:{bg}; padding:10px; border-radius:5px; flex:1; min-width:150px;">'
s4 += f'<p><b>{t}</b></p>'
s4 += '<p>😊 I got it! | 😐 Getting there | 😟 Need help</p>'
s4 += '</div>'
s4 += '</div>'
s4 += '<p style="margin-top:10px;"><b>One thing I learned this week:</b> ' + bl('18em') + '</p>'
s4 += '</div>'
return page(1, "Friday", "Review & Self-Check",
f'''{sec(1, "Estimate First!", s1)}
{sec(2, "Mixed Review", s2)}
{sec(3, "Count and Order", s3)}
{sec(4, "Self-Check & Reflection", s4)}''')
# ═══════════════════════════════════════════════════
# TEACHER GUIDE
# ═══════════════════════════════════════════════════
def teacher_guide():
"""Generate combined teacher guide for all 5 days."""
return tg_page_multi(
"Week 1", "Numbers 101-110 — Teacher Guide",
# Monday
tg_section_title("Monday: Reading & Writing Numbers to 110") +
tg_sec(1, "Count On by 1s", ["103, 104, 106", "107, 108, 109"]) +
tg_sec(2, "Read Number Words", ["101", "104", "108", "110"]) +
tg_sec(3, "Write Number Words", ["one hundred two", "one hundred six", "one hundred nine"]) +
tg_sec(4, "Estimate First", ["102 is closer to 100 (only 2 away)", "109 is closer to 110 (only 1 away)"]) +
tg_sec(5, "Number Talk", ["Aria is right: after 109 comes 110. Sample reasoning: 109 + 1 more = 110; the ones go 9 → 0 and the tens go up by 1."]) +
tg_note("If your child says 'one hundred AND two,' gently model 'one hundred two' — no 'and' in standard form.") +
tg_note("Page break"),
# Tuesday
tg_section_title("Tuesday: Place Value — Hundreds, Tens, Ones") +
tg_sec(1, "Hundreds, Tens, Ones", ["103 = 1 hundred, 0 tens, 3 ones", "106 = 1 hundred, 0 tens, 6 ones", "110 = 1 hundred, 1 ten, 0 ones"]) +
tg_sec(2, "Build the Number", ["105", "109", "110", "102"]) +
tg_sec(3, "Show 108 Two Ways", ["Any two correct representations: base-10 blocks (1 flat + 8 units), 100 + 8, tally marks, ten-frames, etc."]) +
tg_sec(4, "Number Talk", ["110 has more tens: 110 has 1 ten, 104 has 0 tens. Look at the middle digit."]) +
tg_note("Common error: writing 107 as '1 hundred 7 tens.' Use base-10 blocks to show the tens place is EMPTY (zero tens).") +
tg_note("Page break"),
# Wednesday
tg_section_title("Wednesday: Comparing Numbers") +
tg_sec(1, "Compare with <, >, =", ["103 < 108", "110 > 101", "106 = 106", "109 > 104", "102 < 107"]) +
tg_sec(2, "Circle the Greater Number", ["105", "110", "104"]) +
tg_sec(3, "True or False", ["T (107 > 104)", "F (103 is less than 109)", "T (110 = 110)", "F (105 is greater than 102)"]) +
tg_sec(4, "Number Talk", ["110 is larger. Both have 1 hundred, but 110 has 1 ten while 101 has 0 tens — no counting needed."]) +
tg_note("Page break"),
# Thursday
tg_section_title("Thursday: Counting On & Ordering") +
tg_sec(1, "Count On", ["100, 101, 102", "100, 110", "108, 107 (backward)", "120, 130"]) +
tg_sec(2, "Before and After", ["104, 105, 106", "101, 102, 103", "108, 109, 110"]) +
tg_sec(3, "Put Them in Order", ["101, 105, 108", "102, 104, 107, 110", "109, 106, 103"]) +
tg_sec(4, "Word Problems", ["Page 105 (104 + 1 more page)", "No — 101 + 10 = 111, which is more than 110. Only 9 more kids can fit."]) +
tg_sec(5, "Create Your Own", ["Accept any valid comparing problem using two numbers from 101-110 with a correct answer."]) +
tg_note("Page break"),
# Friday
tg_section_title("Friday: Review & Self-Check") +
tg_sec(1, "Estimate First", ["106 is closer to 110 (4 away vs. 6 away)", "101 is closer to 100 (1 away)"]) +
tg_sec(2, "Mixed Review", ["103", "one hundred ten", "104", "102 < 108", "After 106: 107", "Before 105: 104"]) +
tg_sec(3, "Count and Order", ["108, 109", "103, 109, 110"]) +
tg_sec(4, "Self-Check", ["Accept student self-assessment. Discuss the 'one thing I learned' response together."])
)
# ═══════════════════════════════════════════════════
# GENERATE
# ═══════════════════════════════════════════════════
if __name__ == "__main__":
# Clean old files
for f in glob.glob(os.path.join(WEEK, "*.pdf")):
os.remove(f)
for f in glob.glob(os.path.join(WEEK, "*.html")):
os.remove(f)
days = [
(monday, "Monday"),
(tuesday, "Tuesday"),
(wednesday, "Wednesday"),
(thursday, "Thursday"),
(friday, "Friday"),
]
# Generate student worksheets
for lesson_func, day in days:
html = lesson_func()
fname = f"Week_1_{day}"
path = os.path.join(WEEK, f"{fname}.html")
with open(path, "w") as f:
f.write(html)
pdf_path = os.path.join(WEEK, f"{fname}.pdf")
HTML(filename=path).write_pdf(pdf_path)
print(f"Generated: {pdf_path}")
# Generate combined teacher guide
html = teacher_guide()
path = os.path.join(WEEK, "Week_1_Teacher_Guide.html")
with open(path, "w") as f:
f.write(html)
pdf_path = os.path.join(WEEK, "Week_1_Teacher_Guide.pdf")
HTML(filename=path).write_pdf(pdf_path)
print(f"Generated: {pdf_path}")
print("\nWeek 1 complete!")