#!/usr/bin/env python3
"""
Week 2: Numbers 111-120
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 118 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_2")
# ═══════════════════════════════════════════════════
# MONDAY — Reading & Writing Numbers to 120
# ═══════════════════════════════════════════════════
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;">111, 112, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, 115, <u>' + b('3em') + '</u></div>'
s1 += '<div class="abox" style="font-size:17px;">115, 116, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, 120</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 eleven", "one hundred fourteen", "one hundred eighteen", "one hundred twenty"]
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 twelve.")</p>'
s3 += '<div class="mgrid c1">'
for n in ["112", "116", "119"]:
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 110 to 120. Don\'t count — just picture it!</p>'
s4 += '<div class="mgrid c2">'
s4 += '<div class="abox"><p>Is <b>112</b> closer to 110 or 120?</p><p>' + b('5em') + '</p></div>'
s4 += '<div class="abox"><p>Is <b>119</b> closer to 110 or 120?</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 119 is <b>120</b>. Ben says it is <b>1110</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(2, "Monday", "Reading & Writing Numbers to 120",
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 119?", 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> 113 = <b>1 hundred</b> + <b>1 ten</b> + <b>3 ones</b>. And 120 = 1 hundred + <b>2 tens</b> + 0 ones!</p>'
s1 += '</div>'
s1 += '<p class="note">Write how many hundreds, tens, and ones.</p>'
s1 += '<div class="mgrid c1">'
for n in ["113", "116", "120"]:
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 + 1 ten + 5 ones",
"1 hundred + 1 ten + 9 ones",
"1 hundred + 2 tens + 0 ones",
"1 hundred + 1 ten + 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 118 two different ways
s3 = '<div class="abox" style="background:#f3e5f5;">'
s3 += '<p><b>Two Ways!</b> Show the number <b>118</b> two different ways. '
s3 += 'You could draw base-10 blocks, write it as 100 + 10 + 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>114</b> and <b>120</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(2, "Tuesday", "Place Value: Hundreds, Tens, Ones",
f'''{sec(1, "Hundreds, Tens, and Ones", s1)}
{sec(2, "Build the Number", s2)}
{sec(3, "Show 118 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! 113 <b><</b> 118 because 118 is bigger.</p>'
s1 += '</div>'
s1 += '<p class="note">Write <, >, or = in each circle.</p>'
s1 += '<div class="mgrid c2">'
pairs = [("113", "118"), ("120", "111"), ("116", "116"), ("119", "114"), ("112", "117")]
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 [("115", "112"), ("118", "120"), ("111", "114")]:
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 = ["117 > 114", "113 > 119", "120 = 120", "115 < 112"]
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>120</b> or <b>111</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(2, "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: 120 or 111?", s4)}''')
# ═══════════════════════════════════════════════════
# THURSDAY — Counting On & Ordering
# ═══════════════════════════════════════════════════
def thursday():
# 1: Count on by 1s and 10s — forward AND backward
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: 108, 109, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u></div>'
s1 += '<div class="abox" style="font-size:16px;">Count by 10s: 90, 100, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u></div>'
s1 += '<div class="abox" style="font-size:16px;">Count BACKWARD by 1s: 120, 119, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, 116</div>'
s1 += '<div class="abox" style="font-size:16px;">Count by 10s: 100, 110, 120, <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 ["115", "112", "119"]:
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: 118, 111, 115 → <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: 120, 112, 117, 114 → <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: 113, 119, 116 → <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 120 pages. She is on page 114. '
'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 120 kids. There are 111 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 111 and 120. 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(2, "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 110 to 120. Don\'t count!</p>'
s1 += '<div class="mgrid c2">'
s1 += '<div class="abox"><p>Is <b>116</b> closer to 110 or 120?</p><p>' + b('5em') + '</p></div>'
s1 += '<div class="abox"><p>Is <b>111</b> closer to 110 or 120?</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 thirteen</p><p><u>' + b('5em') + '</u></p></div>'
s2 += '<div class="abox"><p>Write the number word for 120:</p><p><u>' + bw('14em') + '</u></p></div>'
s2 += '<div class="abox"><p>1 hundred + 1 ten + 4 ones = <u>' + b('5em') + '</u></p></div>'
s2 += '<div class="abox"><p>Compare: 112 <span class="obox" style="min-width:1.8em; min-height:1.6em;"> </span> 118</p></div>'
s2 += '<div class="abox"><p>What comes AFTER 116? <u>' + b('4em') + '</u></p></div>'
s2 += '<div class="abox"><p>What comes BEFORE 115? <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;">116, 117, <u>' + b('3em') + '</u>, <u>' + b('3em') + '</u>, 120</div>'
s3 += '<div class="abox" style="font-size:16px;">Least to greatest: 119, 113, 120 → <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 111-120?</b></p>'
s4 += '<div style="display:flex; gap:16px; flex-wrap:wrap;">'
topics = [("Reading & Writing to 120", "#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(2, "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 2", "Numbers 111-120 — Teacher Guide",
# Monday
tg_section_title("Monday: Reading & Writing Numbers to 120") +
tg_sec(1, "Count On by 1s", ["113, 114, 116", "117, 118, 119"]) +
tg_sec(2, "Read Number Words", ["111", "114", "118", "120"]) +
tg_sec(3, "Write Number Words", ["one hundred twelve", "one hundred sixteen", "one hundred nineteen"]) +
tg_sec(4, "Estimate First", ["112 is closer to 110 (only 2 away)", "119 is closer to 120 (only 1 away)"]) +
tg_sec(5, "Number Talk", ["Aria is right: after 119 comes 120. Sample reasoning: 119 + 1 more = 120; the ones go 9 → 0 and the tens go up by 1 (1 ten becomes 2 tens)."]) +
tg_note("If your child says 'one hundred AND twelve,' gently model 'one hundred twelve' — 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", ["113 = 1 hundred, 1 ten, 3 ones", "116 = 1 hundred, 1 ten, 6 ones", "120 = 1 hundred, 2 tens, 0 ones"]) +
tg_sec(2, "Build the Number", ["115", "119", "120", "112"]) +
tg_sec(3, "Show 118 Two Ways", ["Any two correct representations: base-10 blocks (1 flat + 1 rod + 8 units), 100 + 10 + 8, tally marks, ten-frames, etc."]) +
tg_sec(4, "Number Talk", ["120 has more tens: 120 has 2 tens, 114 has 1 ten. Look at the middle digit."]) +
tg_note("Common error: reading 120 as 'one hundred two.' Use base-10 blocks to show 2 full rods in the tens place.") +
tg_note("Page break"),
# Wednesday
tg_section_title("Wednesday: Comparing Numbers") +
tg_sec(1, "Compare with <, >, =", ["113 < 118", "120 > 111", "116 = 116", "119 > 114", "112 < 117"]) +
tg_sec(2, "Circle the Greater Number", ["115", "120", "114"]) +
tg_sec(3, "True or False", ["T (117 > 114)", "F (113 is less than 119)", "T (120 = 120)", "F (115 is greater than 112)"]) +
tg_sec(4, "Number Talk", ["120 is larger. Both have 1 hundred, but 120 has 2 tens while 111 has 1 ten — no counting needed."]) +
tg_note("Page break"),
# Thursday
tg_section_title("Thursday: Counting On & Ordering") +
tg_sec(1, "Count On", ["110, 111, 112", "110, 120", "118, 117 (backward)", "130, 140"]) +
tg_sec(2, "Before and After", ["114, 115, 116", "111, 112, 113", "118, 119, 120"]) +
tg_sec(3, "Put Them in Order", ["111, 115, 118", "112, 114, 117, 120", "119, 116, 113"]) +
tg_sec(4, "Word Problems", ["Page 115 (114 + 1 more page)", "No — 111 + 10 = 121, which is more than 120. Only 9 more kids can fit."]) +
tg_sec(5, "Create Your Own", ["Accept any valid comparing problem using two numbers from 111-120 with a correct answer."]) +
tg_note("Page break"),
# Friday
tg_section_title("Friday: Review & Self-Check") +
tg_sec(1, "Estimate First", ["116 is closer to 120 (4 away vs. 6 away)", "111 is closer to 110 (1 away)"]) +
tg_sec(2, "Mixed Review", ["113", "one hundred twenty", "114", "112 < 118", "After 116: 117", "Before 115: 114"]) +
tg_sec(3, "Count and Order", ["118, 119", "113, 119, 120"]) +
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_2_{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_2_Teacher_Guide.html")
with open(path, "w") as f:
f.write(html)
pdf_path = os.path.join(WEEK, "Week_2_Teacher_Guide.pdf")
HTML(filename=path).write_pdf(pdf_path)
print(f"Generated: {pdf_path}")
print("\nWeek 2 complete!")