#!/usr/bin/env python3
"""Generate curriculum wiki pages from extracted curriculum structure.
Creates:
- entities/curriculum/{subject}/topic pages (lesson_topic type)
- concepts/curriculum/ overview pages (concept type)
- Index entries for all new pages
"""
import json
import os
import re
from datetime import date
TODAY = date.today().isoformat()
WIKI = os.path.expanduser("~/wiki")
with open(os.path.join(WIKI, "curriculum_structure.json"), 'r') as f:
data = json.load(f)
lessons = data['lessons']
math_phases = data.get('math_phases', {})
sci_units = data.get('sci_units', {})
ela_phases = data.get('ela_phases', {})
# Ensure dirs exist
for subj in ['math', 'science', 'ela']:
os.makedirs(os.path.join(WIKI, "entities", "curriculum", subj), exist_ok=True)
os.makedirs(os.path.join(WIKI, "concepts", "curriculum"), exist_ok=True)
def slugify(text):
"""Convert topic name to wiki slug."""
s = text.lower().strip()
s = re.sub(r'[^\w\s-]', '', s)
s = re.sub(r'[-_\s]+', '-', s)
s = s.strip('-')
# Keep it reasonable length
if len(s) > 80:
s = s[:77] + '...'
return s
# Build topic -> weeks mapping per subject
topic_weeks = {} # subject -> {topic: [weeks]}
for subject, subject_lessons in lessons.items():
topic_weeks[subject] = {}
for lesson in subject_lessons:
topic = lesson['topic']
week = lesson['week']
if topic not in topic_weeks[subject]:
topic_weeks[subject][topic] = []
if week not in topic_weeks[subject][topic]:
topic_weeks[subject][topic].append(week)
# Map subjects to tag sets and phase/unit info
subject_config = {
'math': {
'phase_map': math_phases,
'phase_field': 'phase',
'standard_prefix': 'CCSS.MATH.CONTENT.2.',
'tags': ['grade-2', 'math', 'homeschool', 'ccss'],
},
'science': {
'phase_map': sci_units,
'phase_field': 'unit',
'standard_prefix': 'NGSS.2-',
'tags': ['grade-2', 'science', 'homeschool', 'ngss'],
},
'ela': {
'phase_map': ela_phases,
'phase_field': 'phase',
'standard_prefix': 'CCSS.ELA-LITERACY.',
'tags': ['grade-2', 'ela', 'homeschool', 'ccss'],
},
}
# Generate lesson topic entities
created_files = []
for subject, subject_lessons in lessons.items():
config = subject_config[subject]
phase_map = config['phase_map']
for topic, weeks in sorted(topic_weeks[subject].items()):
slug = slugify(topic)
filename = f"entities/curriculum/{subject}/{slug}.md"
# Get phase/unit for this topic
phase = None
for w in weeks:
wn = int(w.replace('Week_', ''))
if wn in phase_map:
phase = phase_map[wn]
break
# Build tag list
tags = list(config['tags'])
topic_slug = slugify(topic)
# Add topic-specific tags
topic_lower = topic.lower()
if 'counting' in topic_lower or 'number' in topic_lower:
tags.append('counting')
if 'place value' in topic_lower:
tags.append('place-value')
if 'addition' in topic_lower:
tags.append('addition')
if 'subtraction' in topic_lower:
tags.append('subtraction')
if 'multiplication' in topic_lower:
tags.append('multiplication')
if 'division' in topic_lower:
tags.append('division')
if 'fraction' in topic_lower:
tags.append('fractions')
if 'geometry' in topic_lower or 'shape' in topic_lower:
tags.append('geometry')
if 'measurement' in topic_lower or 'length' in topic_lower or 'time' in topic_lower or 'money' in topic_lower:
tags.append('measurement')
if 'phonics' in topic_lower or 'vowel' in topic_lower or 'silent' in topic_lower or 'digraph' in topic_lower:
tags.append('phonics')
if 'suffix' in topic_lower or 'prefix' in topic_lower:
tags.append('morphology')
if 'spelling' in topic_lower:
tags.append('spelling')
if 'grammar' in topic_lower or 'sentence' in topic_lower or 'noun' in topic_lower or 'verb' in topic_lower:
tags.append('grammar')
if 'synonym' in topic_lower or 'antonym' in topic_lower or 'meaning' in topic_lower or 'context' in topic_lower:
tags.append('vocabulary')
if 'matter' in topic_lower:
tags.append('matter')
if 'plant' in topic_lower:
tags.append('plants')
if 'habitat' in topic_lower or 'ecosystem' in topic_lower:
tags.append('ecosystems')
if 'water' in topic_lower:
tags.append('water-cycle')
if 'weather' in topic_lower or 'climate' in topic_lower:
tags.append('weather')
if 'erosion' in topic_lower or 'rock' in topic_lower or 'earth' in topic_lower:
tags.append('earth-science')
# Deduplicate tags
tags = sorted(set(tags))
# Build related topics (previous/next in curriculum)
all_topics = list(topic_weeks[subject].keys())
topic_idx = None
for i, t in enumerate(all_topics):
tw = weeks[0]
ti = int(tw.replace('Week_', ''))
if t == topic:
topic_idx = ti
break
prev_topic = None
next_topic = None
if topic_idx and topic_idx > 1:
for t in all_topics:
tweeks = topic_weeks[subject][t]
if tweeks:
tw = int(tweeks[0].replace('Week_', ''))
if tw == topic_idx - 1:
prev_topic = slugify(t)
break
if topic_idx and topic_idx < 32:
for t in all_topics:
tweeks = topic_weeks[subject][t]
if tweeks:
tw = int(tweeks[0].replace('Week_', ''))
if tw == topic_idx + 1:
next_topic = slugify(t)
break
# Generate content
content = f"""---
title: "{topic}"
created: {TODAY}
updated: {TODAY}
type: lesson_topic
subject: {subject}
tags: {tags}
weeks: {[int(w.replace('Week_', '')) for w in weeks]}
source: Home_School/2nd_Grade/{subject.replace('_', ' ').title()}/
"""
if phase:
content += f"phase: \"{phase}\"\n"
content += f"""---
## Overview
{topic} — {subject.title()} curriculum topic for 2nd grade.
**Weeks covered:** {', '.join(weeks)}
"""
if phase:
content += f"**Phase/Unit:** {phase}\n"
content += f"""
## Description
"""
# Generate brief description based on topic
topic_lower = topic.lower()
if 'counting' in topic_lower:
content += "Counting and number sense development. Students practice counting by 1s, 5s, and 10s, reading and writing numbers, and using hundreds charts.\n"
elif 'place value' in topic_lower:
content += "Understanding tens and ones place value. Students decompose numbers, use expanded form, and work with base-10 representations.\n"
elif 'comparing' in topic_lower and 'ordering' in topic_lower:
content += "Comparing and ordering numbers using <, >, = symbols. Students order sets of 3-5 numbers from least to greatest.\n"
elif 'addition' in topic_lower and 'facts' in topic_lower:
content += "Addition fact fluency to 20. Number bonds, making 10 strategy, and timed practice for automaticity.\n"
elif 'subtraction' in topic_lower and 'facts' in topic_lower:
content += "Subtraction fact fluency to 20. Relationship to addition, fact families, and fluency practice.\n"
elif 'addition' in topic_lower and 'regrouping' in topic_lower:
content += "Addition with regrouping (carrying). Two-digit and three-digit addition with place value alignment.\n"
elif 'subtraction' in topic_lower and 'regrouping' in topic_lower:
content += "Subtraction with regrouping (borrowing). Open number line strategy and standard algorithm.\n"
elif 'word problem' in topic_lower:
content += "Mathematical word problems requiring reading comprehension, drawing pictures, and multi-step reasoning.\n"
elif 'silent e' in topic_lower or 'long vowel' in topic_lower:
content += "Silent e pattern that makes vowels say their name. Students identify, spell, and read words with the magic e pattern.\n"
elif 'vowel team' in topic_lower:
content += "Vowel team combinations where two vowels work together to make one sound (ai, ay, ee, ea, oa, ow, ou, ew).\n"
elif 'digraph' in topic_lower:
content += "Digraph consonant combinations where two letters make one sound (sh, ch, th, wh, ph, ck).\n"
elif 'r-controlled' in topic_lower:
content += "R-controlled vowels (ar, er, ir, or, ur) where the r changes the vowel sound.\n"
elif 'double consonant' in topic_lower:
content += "Double consonant patterns in spelling. When to double consonants and how they affect pronunciation.\n"
elif 'prefix' in topic_lower:
content += "Word prefixes that change meaning (un-, re-, dis-). Students learn to decode unfamiliar words using prefix knowledge.\n"
elif 'suffix' in topic_lower:
content += "Word suffixes that change word type or degree (-ed, -ing, -s, -es, -er, -est, -ly, -ful, -less).\n"
elif 'homophone' in topic_lower:
content += "Homophones — words that sound the same but have different meanings and spellings.\n"
elif 'synonym' in topic_lower:
content += "Synonyms — words with similar meanings. Students learn to replace words for variety and precision.\n"
elif 'antonym' in topic_lower:
content += "Antonyms — words with opposite meanings. Students explore word pairs and vocabulary relationships.\n"
elif 'context clue' in topic_lower:
content += "Context clues — using surrounding words and sentences to figure out unknown word meanings.\n"
elif 'multiple meaning' in topic_lower:
content += "Words with multiple meanings. Students learn that context determines which meaning applies.\n"
elif 'word famil' in topic_lower or 'root word' in topic_lower:
content += "Word families and root words. Students explore how words relate through common roots and patterns.\n"
elif 'matter' in topic_lower and 'solid' in topic_lower and 'liquid' in topic_lower:
content += "States of matter — solids, liquids, and gases. Students classify materials and observe their properties.\n"
elif 'plant' in topic_lower and 'need' in topic_lower:
content += "What plants need to grow: sunlight, water, air, soil, and space. Students conduct observation experiments.\n"
elif 'habitat' in topic_lower:
content += "Animal and plant habitats — where living things survive. Students explore land and water habitats.\n"
elif 'ecosystem' in topic_lower:
content += "Ecosystems and interdependence — how living and non-living things depend on each other.\n"
elif 'water cycle' in topic_lower:
content += "The water cycle — evaporation, condensation, precipitation, and collection.\n"
elif 'weather' in topic_lower:
content += "Weather and climate — daily weather patterns vs. long-term climate. Recording and comparing weather data.\n"
elif 'erosion' in topic_lower or 'earth' in topic_lower:
content += "Changes to Earth's surface — erosion, weathering, and geological processes.\n"
elif 'rock' in topic_lower or 'soil' in topic_lower:
content += "Rocks and soil — types of rocks, soil composition, and how they form.\n"
elif 'observation' in topic_lower.lower() or 'scientific' in topic_lower.lower():
content += "Scientific observation skills — asking questions, making predictions, and recording findings.\n"
elif 'material' in topic_lower or 'property' in topic_lower:
content += "Properties of materials — color, texture, hardness, flexibility, and absorbency.\n"
elif 'time' in topic_lower.lower() and 'telling' in topic_lower.lower():
content += "Telling time — reading analog and digital clocks, understanding hour, half-hour, and quarter-hour.\n"
elif 'money' in topic_lower.lower():
content += "Money concepts — identifying coins and bills, counting collections, and making change.\n"
elif 'shape' in topic_lower.lower() or 'geometry' in topic_lower.lower():
content += "Geometric shapes and their attributes. Identifying 2D and 3D shapes, counting sides and vertices.\n"
elif 'area' in topic_lower.lower() or 'perimeter' in topic_lower.lower():
content += "Area and perimeter — measuring the space inside and around shapes.\n"
elif 'fraction' in topic_lower.lower():
content += "Introduction to fractions — parts of a whole, halves, thirds, and fourths.\n"
elif 'equal group' in topic_lower.lower() or 'array' in topic_lower.lower():
content += "Equal groups and arrays — foundational concepts for multiplication understanding.\n"
elif 'multiplication' in topic_lower.lower():
content += "Multiplication concepts — repeated addition, multiplication facts, and strategies.\n"
elif 'division' in topic_lower.lower():
content += "Division as equal sharing — the inverse of multiplication.\n"
elif 'review' in topic_lower.lower() or 'assessment' in topic_lower.lower():
content += "Review and assessment of previously learned concepts. Mixed practice and skill demonstration.\n"
elif 'introduction' in topic_lower.lower() or 'course' in topic_lower.lower():
content += "Course introduction and review of foundational skills. Setting expectations and assessing starting points.\n"
else:
content += f"Topic: {topic}. Part of the {subject} curriculum covering this concept with hands-on practice and activities.\n"
# Cross-references
content += "\n## Related Topics\n\n"
if prev_topic:
content += f"- [[{prev_topic}]] (previous week)\n"
if next_topic:
content += f"- [[{next_topic}]] (next week)\n"
content += f"- [[{subject}-curriculum-map]] (full {subject.title()} curriculum overview)\n"
# Write file
filepath = os.path.join(WIKI, filename)
with open(filepath, 'w') as f:
f.write(content)
created_files.append(filename)
print(f" Created: {filename}")
# Generate curriculum overview concept pages
for subject in ['math', 'science', 'ela']:
config = subject_config[subject]
phase_map = config['phase_map']
filename = f"concepts/curriculum/{subject}-curriculum-map.md"
filepath = os.path.join(WIKI, filename)
content = f"""---
title: "{subject.title()} Curriculum Map — 2nd Grade"
created: {TODAY}
updated: {TODAY}
type: concept
subject: {subject}
tags: {config['tags'] + ['curriculum-map', 'grade-2']}
---
## Overview
Complete 2nd grade {subject.title()} curriculum — 32 weeks of instruction organized into phases.
## Curriculum Progression
"""
# Group weeks by phase/unit
phases_seen = {}
for week_num in range(1, 33):
wn = str(week_num).zfill(2)
phase = phase_map.get(week_num, 'General')
if phase not in phases_seen:
phases_seen[phase] = []
topic = topic_weeks[subject].get(f'Week_{wn}', [''])[0] if topic_weeks[subject].get(f'Week_{wn}') else ''
slug = slugify(topic) if topic else ''
if topic:
phases_seen[phase].append(f"| {week_num} | [{topic}]([[{slug}]]) |")
else:
phases_seen[phase].append(f"| {week_num} | *{topic or 'Review'}* |")
for phase, rows in phases_seen.items():
content += f"### {phase}\n\n"
content += "| Week | Topic |\n|------|-------|\n"
content += "\n".join(rows) + "\n\n"
content += f"""## All Topics
"""
for topic in sorted(topic_weeks[subject].keys()):
slug = slugify(topic)
weeks_list = topic_weeks[subject][topic]
content += f"- [[{slug}]] (Weeks {', '.join(weeks_list)})\n"
with open(filepath, 'w') as f:
f.write(content)
created_files.append(filename)
print(f" Created: {filename}")
# Generate cross-curriculum overview
filepath = os.path.join(WIKI, "concepts", "curriculum", "curriculum-overview.md")
content = f"""---
title: "2nd Grade Curriculum Overview"
created: {TODAY}
updated: {TODAY}
type: concept
tags: [grade-2, homeschool, curriculum-map, overview]
---
## Overview
Complete 2nd grade homeschool curriculum covering Math, Science, and English Language Arts.
32 weeks each, designed for a 7-year-old learning at home.
## Subjects
- [[math-curriculum-map]] — 32 weeks, 5 phases (Number Sense → Multiplication)
- [[science-curriculum-map]] — 32 weeks, seasonal units (Matter → Engineering)
- [[ela-curriculum-map]] — 32 weeks, 5 phases (Phonics → Vocabulary in Reading)
## Structure
| Subject | Weeks | Lessons/Week | Total Lessons |
|---------|-------|-------------|---------------|
| Math | 32 | 5 (Mon-Fri) | 160 |
| Science | 32 | 3 (Mon/Wed/Fri) | 96 |
| ELA | 32 | 5 (Mon-Fri) | 160 |
## Key Progressions
- **Math:** Number sense → Operations → Measurement → Geometry → Multiplication/Division
- **Science:** Physical science (matter) → Life science (plants/animals) → Earth science → Engineering
- **ELA:** Phonics patterns → Word meaning → Grammar → Writing integration → Cumulative mastery
"""
with open(filepath, 'w') as f:
f.write(content)
created_files.append("concepts/curriculum/curriculum-overview.md")
print(f" Created: concepts/curriculum/curriculum-overview.md")
print(f"\nTotal files created: {len(created_files)}")
print(f"Files: {json.dumps(created_files, indent=2)}")