from __future__ import annotations from datetime import date, datetime from typing import Any from sqlalchemy.orm import Session from app import models FOCUS_TRACK_LABELS = { "tech_storytelling": "Engaging Tech Storytelling & YouTube/Creator Presence", "keynote_clarity": "Conference Keynote & Architecture Clarity", "camera_confidence": "On-Camera Confidence, Pace & Zero Fillers", "executive_pitch": "Founder / Product Demo & Executive Pitching", } CURRICULUM_DAYS: list[dict[str, Any]] = [ # ─── WEEK 1: Camera Presence & Vocal Foundation ─── { "day": 1, "week": 1, "week_theme": "Camera Presence & Vocal Foundation", "title": "Baseline 60-Second Tech Intro", "skill_focus": "Baseline Assessment", "duration_sec": 60, "mode": "Pitch", "goal": "Establish baseline", "warm_up": "Take 3 slow 4-second nasal breaths, roll your shoulders back, and speak 'Crisp code, clear story, calm lens' three times with chest resonance.", "challenge": "Look directly into the camera lens for 60 seconds and introduce who you are, what technology problem excites you right now, and what you are building or learning.", "teleprompter_script": ( "Hi, I am practicing daily to become a sharper, more engaging technology presenter.\n\n" "Right now, the area of technology that excites me most is how modern software tools turn complex ideas into products anyone can use.\n\n" "Over the next thirty days, I am focusing on speaking with a steady rhythm, clean pauses instead of filler words, and natural eye contact right into the lens.\n\n" "Here is one project I am working on today—and why it matters." ), "outline_cues": [ "0:00 — Direct lens smile + crisp 1-sentence who-you-are hook", "0:15 — One tech problem or shift you care deeply about", "0:35 — What you are currently building, shipping, or exploring", "0:50 — Clean closing takeaway + hold lens contact for 1 beat", ], "target_keywords": ["building", "technology", "problem", "matters"], }, { "day": 2, "week": 1, "week_theme": "Camera Presence & Vocal Foundation", "title": "Talking to the Lens Like One Engineer", "skill_focus": "Eye Contact & Warmth", "duration_sec": 75, "mode": "Storytelling", "goal": "Stronger eye contact", "warm_up": "Place a small mental target on the physical camera ring. Smile lightly before pressing record so your opening frame starts warm.", "challenge": "Explain your favorite programming language, framework, or developer tool as if recommending it across a coffee table to one trusted colleague—holding >75% lens contact.", "teleprompter_script": ( "If we sat down for coffee and you asked me which tool actually saves me hours every single week, here is my honest answer.\n\n" "Most tools promise productivity, however they quietly add configuration overhead.\n\n" "What makes my go-to tool different is speed of feedback. First, you see results in seconds. Second, errors tell you how to fix them.\n\n" "So if you have not tried it on a real weekend build yet, start small—you will feel the difference immediately." ), "outline_cues": [ "Hook: 'If you asked me which tool actually saves me hours every week...'", "Contrast: Why most alternatives feel heavy or slow", "First & Second concrete moments where this tool shines", "Takeaway: One small way the viewer should try it today", ], "target_keywords": ["first", "second", "however", "because"], }, { "day": 3, "week": 1, "week_theme": "Camera Presence & Vocal Foundation", "title": "Replacing Fillers with Power Pauses", "skill_focus": "Filler Elimination", "duration_sec": 90, "mode": "Interview", "goal": "Reduce fillers", "warm_up": "Read 4 sentences out loud and intentionally freeze silently for 1 full second at every period—lips closed, shoulders relaxed.", "challenge": "Explain how an API request travels from a phone screen to a database and back. Whenever you feel 'um', 'uh', or 'like' rising, substitute a silent 1-second pause.", "teleprompter_script": ( "Every time you tap a button in a mobile app, a remarkably fast relay race happens behind the scenes.\n\n" "First, your phone packages that tap into an HTTPS request. [Pause]\n\n" "Second, an API gateway checks your identity and routes the call to the right backend service. [Pause]\n\n" "Third, the service queries the database, shapes only the fields you need, and streams JSON back in milliseconds.\n\n" "Therefore, great app speed is rarely magic—it is clean boundaries at every hop." ), "outline_cues": [ "Hook: Tap-to-screen relay race metaphor", "Step 1: Client packages request [1s silent pause]", "Step 2: Gateway auth + routing [1s silent pause]", "Step 3: Database query + crisp takeaway", ], "target_keywords": ["first", "second", "third", "therefore", "request"], }, { "day": 4, "week": 1, "week_theme": "Camera Presence & Vocal Foundation", "title": "140 WPM Keynote Cadence Control", "skill_focus": "Speaking Pace", "duration_sec": 90, "mode": "Reading", "goal": "Improve pace", "warm_up": "Hum gently on an exhale for 8 seconds, then count 1-to-10 at a relaxed, deliberate one-number-per-half-second tempo.", "challenge": "Deliver a 90-second product update staying inside 125–155 WPM—fast enough to hold attention, unhurried enough that technical nouns land crisply.", "teleprompter_script": ( "Today we are shipping an update that cuts cold-start latency in half for every user on mobile connections.\n\n" "For months, we noticed that first-time loads felt sluggish on real-world cellular networks, even though our lab benchmarks looked green.\n\n" "Because we trimmed bundle bloat and moved heavy parsing off the main thread, pages now become interactive in under one second.\n\n" "Here is what that unlocks for your daily workflow starting right now." ), "outline_cues": [ "Headline metric right up front (cut latency in half)", "Real-world problem vs lab benchmark gap", "Two crisp changes that made it possible", "What users will feel immediately today", ], "target_keywords": ["latency", "because", "interactive", "workflow"], }, { "day": 5, "week": 1, "week_theme": "Camera Presence & Vocal Foundation", "title": "Plain-English Jargon Translation", "skill_focus": "Clarity & Simplicity", "duration_sec": 90, "mode": "Storytelling", "goal": "Reduce fillers", "warm_up": "Pick one buzzword ('distributed cache', 'vector embedding', 'zero-knowledge proof') and state what it does in 10 one-syllable words.", "challenge": "Explain caching, indexing, or AI embeddings on camera so clearly that both a smart product manager and a senior engineer nod along.", "teleprompter_script": ( "Think of a database index like the alphabetical tabs at the back of a thick cookbook.\n\n" "Without an index, finding one recipe means flipping through all five hundred pages every single time someone gets hungry.\n\n" "With an index, you jump straight to the exact page in two steps. However, every extra index costs a tiny bit of work whenever you add a new recipe.\n\n" "So the real engineering craft is indexing what people search constantly—and leaving the rest lean." ), "outline_cues": [ "Everyday visual analogy in sentence one", "What happens without it (the painful slow path)", "What happens with it + the honest engineering tradeoff", "One-sentence rule of thumb to remember", ], "target_keywords": ["index", "however", "so", "tradeoff"], }, { "day": 6, "week": 1, "week_theme": "Camera Presence & Vocal Foundation", "title": "Breaking Monotone Technical Delivery", "skill_focus": "Vocal Variety & Energy", "duration_sec": 90, "mode": "Pitch", "goal": "Stronger eye contact", "warm_up": "Say the sentence 'We cut build time from twenty minutes to forty seconds' three ways: whispered curiosity, bold emphasis on numbers, and warm celebration.", "challenge": "Present a dramatic 'Before vs. After' technical improvement using deliberate pitch contrast on numbers and contrast words.", "teleprompter_script": ( "Twenty-two minutes. That is how long every engineer on our team used to wait just to know if a one-line fix passed CI.\n\n" "People lost focus, switched tabs, and batched risky changes together.\n\n" "Then we parallelized test shards and cached build layers. Twenty-two minutes dropped to forty-five seconds.\n\n" "Suddenly, shipping stopped feeling like waiting at an airport—and started feeling like creative flow again." ), "outline_cues": [ "Punchy number opener with vocal weight ('Twenty-two minutes.')", "Human frustration of the 'Before' state", "The technical unlock + dramatic 'After' number", "Emotional payoff: what changed for the humans", ], "target_keywords": ["minutes", "seconds", "because", "flow"], }, { "day": 7, "week": 1, "week_theme": "Camera Presence & Vocal Foundation", "title": "Week 1 Checkpoint: 2-Min Architecture Walkthrough", "skill_focus": "Integrated Presence", "duration_sec": 120, "mode": "Pitch", "goal": "Improve pace", "warm_up": "20-second posture check + lens framing check (eyes near top third of frame) + 2 deep breaths.", "challenge": "Deliver a crisp 2-minute walkthrough of a system or app you know well—combining steady 135 WPM pace, <2 fillers/min, and >70% lens eye contact.", "teleprompter_script": ( "Let me walk you through how our system turns a raw user recording into actionable coaching in under a minute.\n\n" "First, the browser captures live video, audio loudness, and facial landmarks locally so real-time feedback feels instant.\n\n" "Second, when you save a take, the API validates the recording and stores session metrics cleanly.\n\n" "Third, our analysis pipeline scores speaking pace, filler habits, and structure, then generates targeted drills for your very next rep.\n\n" "Therefore, every single practice session compounds into measurable progress." ), "outline_cues": [ "Promise hook: What the system accomplishes end-to-end", "First layer: Client-side capture & real-time signals", "Second layer: API validation & reliable persistence", "Third layer: Scoring + coaching loop + closing takeaway", ], "target_keywords": ["first", "second", "third", "therefore", "system"], }, # ─── WEEK 2: Clarity, Structure & Technical Explanations ─── { "day": 8, "week": 2, "week_theme": "Clarity, Structure & Technical Explanations", "title": "The 3-Point Rule for Technical Talks", "skill_focus": "Structural Signposting", "duration_sec": 105, "mode": "Pitch", "goal": "Improve pace", "warm_up": "Hold up 1, 2, 3 fingers off-camera as you rehearse your three transitions out loud.", "challenge": "Explain why a team should adopt (or avoid) a specific technology using strict 3-pillar signposting: Headline → First, Second, Third → Bottom line.", "teleprompter_script": ( "Before migrating any production backend, evaluate three concrete signals—not hype.\n\n" "First, look at operational simplicity: can an on-call engineer debug it at 2 a.m.?\n\n" "Second, measure ecosystem maturity: are drivers, observability, and hiring proven?\n\n" "Third, calculate migration cost versus customer value: does this directly improve reliability or shipping velocity?\n\n" "Thus, when all three align, move decisively; otherwise, invest in your core product." ), "outline_cues": [ "Headline rule: 3 signals before any migration", "First: 2 a.m. debuggability", "Second: Ecosystem & observability maturity", "Third: Customer value vs migration tax + Bottom line", ], "target_keywords": ["first", "second", "third", "thus", "reliability"], }, { "day": 9, "week": 2, "week_theme": "Clarity, Structure & Technical Explanations", "title": "Hooking Viewers in the First 8 Seconds", "skill_focus": "Cold-Open Hooks", "duration_sec": 75, "mode": "Storytelling", "goal": "Stronger eye contact", "warm_up": "Eliminate throat-clearing openers ('Hey guys, so today I wanted to...'). Start directly on the tension!", "challenge": "Start your recording with zero preamble—deliver an 8-second cold-open hook about a surprising software myth, then back it up in 60 seconds.", "teleprompter_script": ( "Adding more servers made our application slower—not faster. Here is why.\n\n" "When traffic spiked last quarter, we doubled our compute instances, expecting response times to drop.\n\n" "However, every new instance opened fresh connections against a single unpooled database, saturating locks within seconds.\n\n" "Once we added connection pooling and read replicas, latency dropped eighty percent on half the hardware.\n\n" "So before scaling horizontally, always find the shared bottleneck first." ), "outline_cues": [ "0:00–0:08 Cold open paradox ('Adding more servers made us slower.')", "0:08–0:30 What we expected vs what broke", "0:30–0:55 Connection pooling fix & exact metric win", "0:55–1:15 Memorable engineering principle", ], "target_keywords": ["however", "so", "first", "latency", "database"], }, { "day": 10, "week": 2, "week_theme": "Clarity, Structure & Technical Explanations", "title": "Explaining Tradeoffs Without Rambling", "skill_focus": "Concise Reasoning", "duration_sec": 120, "mode": "Debate", "goal": "Reduce fillers", "warm_up": "Practice the crisp formula: 'Option A wins when X; Option B wins when Y; for our constraints, choose A because Z.'", "challenge": "Compare SQL vs NoSQL, Monolith vs Microservices, or Local vs Cloud AI in 2 minutes without circling back or repeating yourself.", "teleprompter_script": ( "Choosing between local on-device AI and cloud frontier models comes down to three tradeoffs: privacy, latency, and reasoning depth.\n\n" "First, local models win when sensitive audio or documents cannot leave the user's machine and sub-second offline response matters.\n\n" "However, cloud models win when tasks require broad world knowledge and multi-step synthesis across huge contexts.\n\n" "Therefore, the smartest modern apps combine both: fast local models for instant feedback, paired with cloud reasoning only when needed." ), "outline_cues": [ "Frame the 3 axes up front (privacy, latency, depth)", "When Path A wins decisively", "However — when Path B wins decisively", "Therefore — clear hybrid recommendation", ], "target_keywords": ["first", "however", "therefore", "latency", "models"], }, { "day": 11, "week": 2, "week_theme": "Clarity, Structure & Technical Explanations", "title": "Visual Analogies for Invisible Systems", "skill_focus": "Mental Models", "duration_sec": 90, "mode": "Storytelling", "goal": "Improve pace", "warm_up": "Use slight hand gestures inside the chest-to-shoulder frame to illustrate spatial relationships.", "challenge": "Use a vivid physical-world analogy to explain load balancing, rate limiting, Kubernetes, or Git branching on camera.", "teleprompter_script": ( "Rate limiting works just like the metered green light on a busy highway on-ramp during rush hour.\n\n" "If five hundred cars surge onto the freeway at the exact same second, every lane grinds to a standstill for miles.\n\n" "By spacing entries one car every two seconds, traffic on the main highway keeps flowing at sixty miles per hour.\n\n" "Similarly, an API rate limiter protects every customer's experience when one noisy client suddenly spikes." ), "outline_cues": [ "Concrete real-world picture (highway ramp meter)", "What breaks without it (gridlock)", "How the mechanism restores smooth flow", "Bridge back to software architecture", ], "target_keywords": ["rate", "traffic", "api", "protects"], }, { "day": 12, "week": 2, "week_theme": "Clarity, Structure & Technical Explanations", "title": "Teleprompter Naturalness Mastery", "skill_focus": "Conversational Script Reading", "duration_sec": 90, "mode": "Reading", "goal": "Stronger eye contact", "warm_up": "Set teleprompter font size comfortable near the top of your screen so your eyes barely move left-to-right.", "challenge": "Read today's scripted product announcement using Auto-Scroll Teleprompter mode while sounding 100% spontaneous—using micro-smiles, eyebrow lifts, and natural breaths.", "teleprompter_script": ( "Have you ever recorded a great product demo, watched it back, and realized you stared six inches below the lens the entire time?\n\n" "We built an on-lens studio teleprompter right into your browser to solve that exact problem.\n\n" "Because your script sits right beneath your camera, your eyes stay locked with your audience while your pacing stays effortless.\n\n" "Try one ninety-second take today—and watch how much more confident your playback looks." ), "outline_cues": [ "Conversational question hook with warm eyebrow lift", "Announce the solution cleanly", "Explain why it feels natural on playback", "Friendly direct invitation to try it", ], "target_keywords": ["because", "camera", "script", "confident"], }, { "day": 13, "week": 2, "week_theme": "Clarity, Structure & Technical Explanations", "title": "Answering Tough Technical Questions on Camera", "skill_focus": "Composure Under Pressure", "duration_sec": 90, "mode": "Interview", "goal": "Reduce fillers", "warm_up": "Practice the 2-second 'Acknowledge + Direct Answer' pause: nod once, inhale, state the answer in sentence one.", "challenge": "Answer a skeptical question—'Why won't big incumbents crush your product in six months?' or 'What is the biggest flaw in your architecture?'—with calm honesty.", "teleprompter_script": ( "That is a fair question, and the honest answer is that every architecture has a ceiling if traffic grows tenfold.\n\n" "First, our current single-region database keeps latency low and iteration fast for our current scale.\n\n" "However, we already isolated tenant writes behind clean queue boundaries so we can shard horizontally before contention hits.\n\n" "So we are intentionally optimizing for learning speed today without painting ourselves into a corner tomorrow." ), "outline_cues": [ "Calm acknowledgment + direct answer in sentence 1", "First: Why today's design is deliberately pragmatic", "However: The escape hatch already built in", "So: Strategic takeaway with steady lens contact", ], "target_keywords": ["first", "however", "so", "latency", "architecture"], }, { "day": 14, "week": 2, "week_theme": "Clarity, Structure & Technical Explanations", "title": "Week 2 Checkpoint: 3-Minute Live Product Demo Pitch", "skill_focus": "Structured Demo Delivery", "duration_sec": 150, "mode": "Pitch", "goal": "Improve pace", "warm_up": "Review your Week 1 vs Week 2 filler rate on Progress, then set 1 intention for this checkpoint take.", "challenge": "Deliver a 2.5-minute product demo pitch: Hook → User Pain → How It Works (3 steps) → Proof/Metric → Clear Call to Action.", "teleprompter_script": ( "Great engineers often build extraordinary software—yet lose the room in the first thirty seconds when presenting it on camera.\n\n" "The problem is rarely knowledge; it is lack of structured daily feedback on pace, filler habits, and lens presence.\n\n" "First, our studio pairs an on-lens teleprompter with live WPM and eye-contact cues.\n\n" "Second, every saved session generates concrete coaching drills tailored to your exact bottlenecks.\n\n" "Third, weekly comparisons let you watch your Day 1 self side-by-side against today.\n\n" "Start with just one daily take—and turn presenting into your unfair career advantage." ), "outline_cues": [ "0:00 Hook: Great builders losing the room on camera", "0:25 Root problem: No tight feedback loop", "0:50 First, Second, Third product pillars", "2:00 Closing vision & crisp call to action", ], "target_keywords": ["first", "second", "third", "problem", "feedback"], }, # ─── WEEK 3: Technology News & Engaging Storytelling ─── { "day": 15, "week": 3, "week_theme": "Technology News & Engaging Storytelling", "title": "60-Second Breaking Tech News Briefing", "skill_focus": "News Synthesis", "duration_sec": 60, "mode": "Storytelling", "goal": "Improve pace", "warm_up": "Open the Tech News tab, pick a fresh story, or use today's built-in AI infrastructure briefing.", "challenge": "Deliver a sharp 60-second tech news segment: What just happened → Why builders should care → Your 1-sentence take.", "teleprompter_script": ( "A major shift is happening in AI engineering this year: inference cost per token has fallen nearly tenfold, yet total compute spend is climbing.\n\n" "Why? Because teams are moving from single chat prompts to multi-step background agents that verify code, run tests, and query tools autonomously.\n\n" "For developers, this means latency budgets and evaluation harnesses now matter far more than prompt tricks.\n\n" "My take: the winners next year will be the teams with the cleanest verification loops." ), "outline_cues": [ "Headline shift: Inference cheaper, total agent compute rising", "Why it is happening (single prompt -> multi-step tool loops)", "What changes for builders right now", "Sharp personal prediction in the final 10 seconds", ], "target_keywords": ["because", "inference", "agents", "latency"], }, { "day": 16, "week": 3, "week_theme": "Technology News & Engaging Storytelling", "title": "The Engineering Postmortem War Story", "skill_focus": "Narrative Tension", "duration_sec": 120, "mode": "Storytelling", "goal": "Stronger eye contact", "warm_up": "Great tech stories need stakes! State the exact moment you knew something was wrong in your first two sentences.", "challenge": "Tell a 2-minute story about a tricky bug, outage, or failed experiment: The Stakes → The Red Herring → The Root Cause → The Lesson.", "teleprompter_script": ( "At 4:55 p.m. on a Friday launch, our checkout dashboard suddenly flatlined to zero orders—while CPU and memory looked completely normal.\n\n" "At first, everyone suspected the payment gateway. However, test charges succeeded in sandbox.\n\n" "Twenty minutes in, we inspected a tiny CSS deployment and realized an invisible modal overlay was intercepting mobile taps on Safari.\n\n" "We rolled back in ninety seconds, and orders surged back. Therefore, we added real-browser synthetic click tests to every deploy." ), "outline_cues": [ "Scene & stakes (Friday launch, zero orders, green metrics)", "The red herring we chased first", "The surprising root cause discovery", "The permanent guardrail lesson", ], "target_keywords": ["first", "however", "therefore", "launch"], }, { "day": 17, "week": 3, "week_theme": "Technology News & Engaging Storytelling", "title": "Contrarian Tech Opinion with Evidence", "skill_focus": "Persuasive Point of View", "duration_sec": 105, "mode": "Debate", "goal": "Reduce fillers", "warm_up": "State a bold opinion calmly—persuasion on camera comes from measured certainty, not volume.", "challenge": "Challenge a popular tech consensus (e.g., 'Boring tech beats bleeding-edge stacks for 90% of startups') backed by concrete evidence and fair nuance.", "teleprompter_script": ( "Unpopular engineering opinion: choosing 'boring' proven technology is the fastest way to build a radical product.\n\n" "First, every hour you spend debugging an alpha framework is an hour stolen from talking to users.\n\n" "Second, battle-tested databases and web frameworks have decades of documented failure modes.\n\n" "However, save your innovation budget for the one core algorithm or UX workflow that truly differentiates you.\n\n" "So keep your plumbing boring—so your product can be bold." ), "outline_cues": [ "Bold contrarian thesis in sentence 1", "First & Second concrete proofs", "Fair nuance ('However, where you SHOULD innovate')", "Quotable closing line ('Keep plumbing boring so product is bold')", ], "target_keywords": ["first", "second", "however", "so", "product"], }, { "day": 18, "week": 3, "week_theme": "Technology News & Engaging Storytelling", "title": "Founder & Builder Origin Story Arc", "skill_focus": "Authentic Connection", "duration_sec": 120, "mode": "Storytelling", "goal": "Stronger eye contact", "warm_up": "Recall the exact personal frustration that sparked a project you care about.", "challenge": "Share the origin story behind something you built or why you entered tech: Frustration → Spark → First Prototype → Where It's Going.", "teleprompter_script": ( "The best developer tools almost always start as a personal scratch you could not ignore.\n\n" "A year ago, I dreaded watching my own recorded tech talks because nobody teaches engineers how to speak naturally to a glass camera lens.\n\n" "So I hacked together a weekend prototype that tracked my speaking pace and filler words right inside the browser.\n\n" "Today, that weekend experiment guides my daily practice—because confidence on camera is a trainable skill, not a personality trait." ), "outline_cues": [ "Universal truth hook", "Personal moment of frustration", "The scrappy weekend prototype", "Mission statement: why it matters for others", ], "target_keywords": ["so", "because", "camera", "prototype", "confidence"], }, { "day": 19, "week": 3, "week_theme": "Technology News & Engaging Storytelling", "title": "90-Second Live Headline Synthesis", "skill_focus": "Bullet-Cue Fluency", "duration_sec": 90, "mode": "Storytelling", "goal": "Reduce fillers", "warm_up": "Switch the Studio Teleprompter to 'Cue Cards' mode so you speak from 4 bullets instead of reading full sentences!", "challenge": "Speak ONLY from the 4 bullet cues (no word-for-word reading!) to break down a major trend in developer tooling, cloud, or AI.", "teleprompter_script": ( "Speak freely from your 4 bullet cues today:\n" "1. State the headline trend in plain English.\n" "2. Give one concrete developer workflow example.\n" "3. Name one risk or hype trap to watch out for.\n" "4. Close with what you are testing personally this week." ), "outline_cues": [ "1. Headline trend in 1 crisp sentence", "2. Concrete developer workflow example ('For instance...')", "3. Honest risk or hype trap ('However...')", "4. What I am testing next ('Therefore...')", ], "target_keywords": ["however", "therefore", "workflow", "testing"], }, { "day": 20, "week": 3, "week_theme": "Technology News & Engaging Storytelling", "title": "Human Impact Behind Technical Specs", "skill_focus": "Audience Empathy", "duration_sec": 105, "mode": "Pitch", "goal": "Stronger eye contact", "warm_up": "For every technical metric ('99.99% uptime', '40KB bundle'), ask: 'Whose Tuesday afternoon gets better because of this?'", "challenge": "Turn three dry technical specs into human stories—connecting engineering craft to real people on slow phones, tight budgets, or high-stakes jobs.", "teleprompter_script": ( "When we say we trimmed our web app bundle by eighty percent, that sounds like a dry benchmark.\n\n" "However, in the real world, that means a founder checking analytics on a congested train or a student on a budget phone gets instant answers instead of a blank spinner.\n\n" "First, offline-first caching respects unreliable networks. Second, responsive layouts respect small screens.\n\n" "Ultimately, performance engineering is empathy written in code." ), "outline_cues": [ "Start with the dry technical spec", "Translate it immediately to a human moment", "First & Second ways software respects the user", "Closing line: 'Performance engineering is empathy in code'", ], "target_keywords": ["however", "first", "second", "performance"], }, { "day": 21, "week": 3, "week_theme": "Technology News & Engaging Storytelling", "title": "Week 3 Checkpoint: 3-Min Tech Show Segment", "skill_focus": "Broadcast Storytelling", "duration_sec": 180, "mode": "Storytelling", "goal": "Improve pace", "warm_up": "Pick a headline from Tech News, generate a 2-Min Explainer Storyboard, and customize your personal angle.", "challenge": "Host a complete 3-minute technology commentary segment as if recording for YouTube or a company all-hands—combining hook, story, analogy, and sharp takeaway.", "teleprompter_script": ( "Welcome back. Today we are unpacking one of the biggest shifts in modern software development—and what it actually means for how we build.\n\n" "First, let us look at what just changed beneath the surface.\n\n" "Second, think of the underlying architecture through a simple mental model so we separate real signal from marketing noise.\n\n" "However, every new capability introduces fresh failure modes around reliability and security.\n\n" "Therefore, here are the two practical habits worth adopting on your projects this month." ), "outline_cues": [ "0:00 Broadcast cold open + promise to the viewer", "0:30 First: What changed + concrete facts", "1:15 Second: Analogy that makes the mechanism click", "2:00 However / Therefore: Risks + 2 actionable takeaways", ], "target_keywords": ["first", "second", "however", "therefore", "architecture"], }, # ─── WEEK 4: High-Stakes Presenting, Polish & Signature Style ─── { "day": 22, "week": 4, "week_theme": "High-Stakes Presenting, Polish & Signature Style", "title": "90-Second Executive Engineering Briefing", "skill_focus": "Bottom-Line-Up-Front (BLUF)", "duration_sec": 90, "mode": "Pitch", "goal": "Improve pace", "warm_up": "Executives decide in 20 seconds: state Recommendation → Impact → Risk Mitigation → Ask.", "challenge": "Pitch a technical roadmap decision in 90 seconds using Bottom-Line-Up-Front (BLUF) clarity.", "teleprompter_script": ( "My recommendation is to dedicate two weeks this sprint to automated end-to-end checkout reliability before launching our new tier.\n\n" "First, last month's regressions cost twelve hours of engineering firefighting and delayed two releases.\n\n" "Second, a deterministic test suite cuts release verification from two hours to six minutes.\n\n" "Therefore, investing ten days now protects revenue on launch day and accelerates every sprint after." ), "outline_cues": [ "Sentence 1: Clear recommendation up front", "First: Cost of status quo in hours/risk", "Second: Measurable speedup from proposed investment", "Therefore: Strategic payoff + crisp ask", ], "target_keywords": ["first", "second", "therefore", "reliability"], }, { "day": 23, "week": 4, "week_theme": "High-Stakes Presenting, Polish & Signature Style", "title": "Pattern Interrupts & Re-Engaging Attention", "skill_focus": "Audience Retention", "duration_sec": 120, "mode": "Storytelling", "goal": "Stronger eye contact", "warm_up": "Plan a deliberate 'reset phrase' at 0:45 ('Now pause and look at what happens next...').", "challenge": "Deliver a 2-minute technical talk that intentionally resets audience attention at the 45-second and 90-second marks using rhetorical questions and pace shifts.", "teleprompter_script": ( "Most presentations lose half the room right around the forty-five-second mark—not because the topic is dull, but because the rhythm never changes.\n\n" "First, establish your core technical premise clearly and briskly.\n\n" "Now pause for a second: what actually happens when real users hit this system at peak load?\n\n" "That single question wakes up every listener's brain because curiosity demands an answer.\n\n" "So vary your cadence, ask sharp questions, and earn attention every forty-five seconds." ), "outline_cues": [ "0:00 Premise setup at brisk 145 WPM", "0:45 Pattern interrupt: Slow down + ask sharp question", "1:15 Concrete technical payoff", "1:45 Crisp closing principle", ], "target_keywords": ["first", "because", "so", "system"], }, { "day": 24, "week": 4, "week_theme": "High-Stakes Presenting, Polish & Signature Style", "title": "Graceful Recovery When Losing Your Place", "skill_focus": "Live Resilience", "duration_sec": 90, "mode": "Interview", "goal": "Reduce fillers", "warm_up": "Practice bridging calmly without apologizing: 'Let me zoom back out to the core point...'", "challenge": "Speak impromptu on a moderately complex tech topic; mid-way through, intentionally stop for 2 seconds, smile calmly, use a clean bridge phrase, and finish strong with zero 'um/sorry'.", "teleprompter_script": ( "Even seasoned keynote speakers occasionally lose a detail mid-sentence under bright studio lights.\n\n" "Amateurs apologize, look down, and fill the air with 'um, sorry, wait'.\n\n" "Professionals simply pause, breathe, look squarely into the lens, and bridge with: 'Here is the core point that matters most.'\n\n" "Because the audience does not have your script, calm silence always looks intentional." ), "outline_cues": [ "Open impromptu on how a favorite system works", "At 0:40, intentionally pause silently for 2 full seconds", "Bridge cleanly: 'Stepping back, here is what matters most...'", "Land a confident closing sentence", ], "target_keywords": ["because", "pause", "matters", "lens"], }, { "day": 25, "week": 4, "week_theme": "High-Stakes Presenting, Polish & Signature Style", "title": "Product Launch Keynote Opener", "skill_focus": "Keynote Presence", "duration_sec": 120, "mode": "Pitch", "goal": "Stronger eye contact", "warm_up": "Stand up if possible (or sit tall at the front edge of your chair) for maximum breath support and keynote energy!", "challenge": "Deliver a 2-minute Apple/Stripe-style product launch opener blending scripted precision on the headline lines with natural warmth in the middle.", "teleprompter_script": ( "Every developer remembers the magic of shipping their very first idea to the web—and the frustration of how complicated modern deployment slowly became.\n\n" "Today, we are making shipping feel effortless again.\n\n" "First, zero-config previews spin up on every branch in three seconds.\n\n" "Second, built-in observability highlights real user bottlenecks automatically.\n\n" "Third, rollbacks happen in a single click—so your team can ship boldly every single day." ), "outline_cues": [ "Shared developer memory + tension", "Keynote reveal line with 1-second pause before & after", "Three crisp capabilities (3s previews, observability, 1-click rollback)", "Inspiring close with warm lens smile", ], "target_keywords": ["first", "second", "third", "so", "shipping"], }, { "day": 26, "week": 4, "week_theme": "High-Stakes Presenting, Polish & Signature Style", "title": "Crisp On-Camera Tutorial Teaching", "skill_focus": "Instructional Clarity", "duration_sec": 120, "mode": "Reading", "goal": "Improve pace", "warm_up": "Use the teaching triad: 'What we will build → Why we do this step → Common pitfall to avoid.'", "challenge": "Teach a 3-step technical mini-tutorial on camera (e.g., setting up JWT auth, writing a clean SQL query, or debugging network waterfalls) in 2 minutes.", "teleprompter_script": ( "In the next two minutes, you will learn how to fix slow API waterfalls in any frontend app.\n\n" "First, open your network tab and spot sequential requests that wait on each other unnecessarily.\n\n" "Second, group independent fetches with Promise.all so they fire in parallel.\n\n" "However, watch out for one pitfall: use Promise.allSettled when an optional panel should not crash the whole page.\n\n" "Try this on your dashboard route today and watch load time drop." ), "outline_cues": [ "Promise: What the viewer learns in 2 minutes", "Step 1: How to diagnose the issue", "Step 2: Exact pattern to apply", "Pitfall guardrail ('However...') + quick win", ], "target_keywords": ["first", "second", "however", "parallel"], }, { "day": 27, "week": 4, "week_theme": "High-Stakes Presenting, Polish & Signature Style", "title": "Fireside Q&A Rapid-Fire Precision", "skill_focus": "Impromptu Brevity", "duration_sec": 120, "mode": "Interview", "goal": "Reduce fillers", "warm_up": "Answer each question in 3 sentences max: Direct answer → Concrete example → Takeaway.", "challenge": "Answer TWO rapid-fire tech interview / podcast questions back-to-back in 60 seconds each: (1) Biggest shift in software right now? (2) Best habit you ever built as an engineer?", "teleprompter_script": ( "Question One: What is the biggest shift in software engineering right now?\n" "Answer in three crisp sentences with one real example.\n\n" "Question Two: What is the single highest-leverage habit you have built in your career?\n" "Answer in three crisp sentences and land cleanly at two minutes." ), "outline_cues": [ "Q1 (0:00–1:00): Headline answer -> Example -> Takeaway", "Clean 1.5s transition breath at 1:00", "Q2 (1:00–2:00): Habit -> Story -> Advice to listener", ], "target_keywords": ["because", "first", "habit", "software"], }, { "day": 28, "week": 4, "week_theme": "High-Stakes Presenting, Polish & Signature Style", "title": "Zero-Filler 2-Minute Mastery Sprint", "skill_focus": "Peak Articulation", "duration_sec": 120, "mode": "Debate", "goal": "Reduce fillers", "warm_up": "Slow your opening sentence by 10%—most fillers happen when your mouth outruns your next thought.", "challenge": "Speak for a full 2 minutes on any technology topic of your choice with ZERO filler words (<1.0/min) while keeping pace above 125 WPM.", "teleprompter_script": ( "Today is a precision challenge: two full minutes of clear, unhurried technical commentary with zero filler crutches.\n\n" "First, state a technology thesis you genuinely believe in.\n\n" "Second, walk through two real-world examples from products or systems you admire.\n\n" "Third, pause deliberately before your final sentence—and deliver a closing line worth quoting." ), "outline_cues": [ "0:00 Calm, unhurried thesis statement", "0:30 Example 1 with crisp transitions", "1:15 Example 2 + contrast ('However...')", "1:50 1-second silent pause -> Quotable closing line", ], "target_keywords": ["first", "second", "third", "however"], }, { "day": 29, "week": 4, "week_theme": "High-Stakes Presenting, Polish & Signature Style", "title": "Dress Rehearsal: Signature 3-Min Tech Talk", "skill_focus": "Signature Voice", "duration_sec": 180, "mode": "Storytelling", "goal": "Stronger eye contact", "warm_up": "Load your own custom script or outline into the Studio Teleprompter and set Cue Cards or Auto-Scroll.", "challenge": "Deliver a 3-minute dress rehearsal of a signature talk, product demo, or YouTube episode you want to publish in the real world.", "teleprompter_script": ( "Open with a bold problem or surprising insight from your own work.\n\n" "First, show why conventional approaches fall short.\n\n" "Second, reveal the core insight or architecture that changes the game, anchored in a vivid analogy.\n\n" "Third, share measurable proof or a real war story.\n\n" "Finally, leave your audience with one concrete action they can take today." ), "outline_cues": [ "0:00 Cold-open hook with energy & direct lens lock", "0:40 Conventional approach & why it breaks", "1:30 Core insight + visual analogy + proof", "2:30 Actionable takeaway + confident sign-off", ], "target_keywords": ["first", "second", "third", "problem"], }, { "day": 30, "week": 4, "week_theme": "High-Stakes Presenting, Polish & Signature Style", "title": "Graduation Capstone & Day 1 Comparison", "skill_focus": "Mastery & Reflection", "duration_sec": 120, "mode": "Pitch", "goal": "Stronger eye contact", "warm_up": "Breathe deeply, smile at the lens, and own the frame—you have built a real presenting habit.", "challenge": "Re-record your Tech Presenter Introduction & Vision (2 minutes), then open Progress & Compare to watch Day 30 side-by-side against Day 1!", "teleprompter_script": ( "Thirty days ago, I started practicing on camera to turn technical ideas into clear, compelling stories.\n\n" "First, I learned to replace rushed filler words with calm, deliberate pauses.\n\n" "Second, I learned to speak directly to the camera lens as if conversing with one curious builder.\n\n" "Third, I learned to structure complex engineering ideas into hooks, analogies, and clear takeaways.\n\n" "Here is the technology problem I am tackling next—and why I am excited to share the journey." ), "outline_cues": [ " Hook: Who you are as a builder & tech communicator today", " First, Second, Third breakthroughs in how you communicate", " The exciting technical frontier you are tackling next", " Open Progress & Compare afterward to watch Day 30 vs Day 1!", ], "target_keywords": ["first", "second", "third", "camera", "stories"], }, ] DAILY_WARMUPS: list[dict[str, Any]] = [ { "id": "warmup-breath-pace", "title": "4-4-6 Diaphragmatic Pace Reset", "category": "Breath & Calm", "duration_sec": 60, "steps": [ "Sit or stand tall with your collarbone open and camera at eye height.", "Inhale quietly through your nose for 4 seconds, expanding your lower ribs.", "Hold gently for 4 seconds with zero jaw or throat tension.", "Exhale on a steady 'ssss' hiss for 6 seconds—repeat 4 cycles before hitting Record.", ], "read_aloud_text": "Steady breath creates steady authority. My pace gives every listener time to think.", }, { "id": "warmup-tech-plosives", "title": "Crisp Tech Consonant & Plosive Articulation", "category": "Articulation", "duration_sec": 75, "steps": [ "Loosen your jaw and exaggerate lip and tongue movement by 20%.", "Read the technical articulation phrase below slowly once, then at brisk 145 WPM.", "Keep word endings ('-ed', '-ts', '-ks') crisp rather than swallowed.", ], "read_aloud_text": ( "Packet pipelines parse predictable payloads; distributed databases deduplicate durable commits; " "clean caches cut cold-start compute costs." ), }, { "id": "warmup-pitch-staircase", "title": "Vocal Variety & Pitch Staircase", "category": "Expressiveness", "duration_sec": 60, "steps": [ "Read sentence 1 in a low, grounded register (calm certainty).", "Read sentence 2 with upward curiosity on the question.", "Read sentence 3 punching the contrast numbers and pausing before the final word.", ], "read_aloud_text": ( "Most systems fail quietly at the edges. What happens when ten thousand users reconnect at once? " "Latency drops from twelve seconds... to eighty milliseconds." ), }, { "id": "warmup-silent-pause", "title": "The 1-Second Power Pause Metronome", "category": "Filler Control", "duration_sec": 60, "steps": [ "Read each clause aloud while looking straight into the camera ring.", "At every [PAUSE], close your lips completely and count 'one-thousand' silently.", "Notice how calm silence sounds confident rather than awkward.", ], "read_aloud_text": ( "Great presenters never rush the punchline. [PAUSE] First, they frame the tension. [PAUSE] " "Second, they reveal the mechanism. [PAUSE] Finally, they let the takeaway breathe." ), }, ] CAMERA_CHALLENGES: list[dict[str, Any]] = [ { "id": "challenge-lens-lock", "title": "60s Lens-Lock Challenge", "badge": "Camera Presence", "mode": "Storytelling", "goal": "Stronger eye contact", "duration_sec": 60, "target_metric": "eye_contact >= 75%", "prompt": "Explain how HTTPS or public-key encryption keeps data safe—without breaking eye contact with the camera lens for more than 2 seconds at a time.", "outline_cues": [ "Analogy: A padlock anyone can snap shut, but only one key opens", "How browser + server agree on a secret session key", "Why this protects every login and payment online", ], "target_keywords": ["key", "browser", "secure", "because"], }, { "id": "challenge-zero-filler-sprint", "title": "90s Zero-Filler Architecture Sprint", "badge": "Articulation", "mode": "Interview", "goal": "Reduce fillers", "duration_sec": 90, "target_metric": "filler_rate <= 1.5/min", "prompt": "Walk through what happens when you type a URL into a browser and press Enter. Replace every urge to say 'um', 'uh', or 'like' with a silent pause.", "outline_cues": [ "First: DNS lookup translates domain to IP", "Second: TCP + TLS handshake establishes secure channel", "Third: HTTP response streams HTML & renders pixels", ], "target_keywords": ["first", "second", "third", "browser", "response"], }, { "id": "challenge-cold-open-hooks", "title": "Triple Cold-Open Hook Lab", "badge": "Engagement", "mode": "Pitch", "goal": "Stronger eye contact", "duration_sec": 60, "target_metric": "Expressive tone + Smile", "prompt": "Deliver 3 different 15-second video hooks back-to-back for the same tech project: (1) Surprising Stat Hook, (2) Relatable Frustration Hook, (3) Bold Contrarian Hook.", "outline_cues": [ "Hook 1 (0:00–0:20): Start with a dramatic number or benchmark", "Hook 2 (0:20–0:40): 'Have you ever spent three hours debugging...'", "Hook 3 (0:40–1:00): 'Everyone thinks X solves Y—however...'", ], "target_keywords": ["however", "because", "seconds"], }, { "id": "challenge-explain-3-levels", "title": "Explain It at 3 Levels (Non-Tech → Dev → CTO)", "badge": "Clarity", "mode": "Storytelling", "goal": "Improve pace", "duration_sec": 120, "target_metric": "125–155 WPM + High Clarity", "prompt": "Pick one concept (APIs, Containers, Vector Search, or Caching) and explain it in 35s to a smart friend, 40s to a junior developer, and 40s to a CTO focused on cost & reliability.", "outline_cues": [ "Level 1 (Friend): Zero jargon, everyday analogy", "Level 2 (Developer): How you wire it in code & debug it", "Level 3 (CTO): Latency, cost, scale, and operational risk", ], "target_keywords": ["first", "second", "latency", "cost", "reliability"], }, { "id": "challenge-hot-seat-postmortem", "title": "Impromptu Incident Briefing Hot-Seat", "badge": "Executive Calm", "mode": "Interview", "goal": "Improve pace", "duration_sec": 90, "target_metric": "Steady 130–150 WPM", "prompt": "Imagine an API outage was just mitigated 5 minutes ago. Deliver a calm, transparent 90-second video update to customers & teammates: Impact → Root Cause → Fix → Prevention.", "outline_cues": [ "Status first: Service is restored and healthy", "Impact window & who was affected", "Plain-English root cause (no blame)", "Two concrete guardrails shipping this week", ], "target_keywords": ["first", "because", "therefore", "restored"], }, ] def get_or_create_profile(db: Session, user_id: int) -> models.PresenterProfile: profile = ( db.query(models.PresenterProfile) .filter(models.PresenterProfile.user_id == user_id) .first() ) if profile is None: profile = models.PresenterProfile( user_id=user_id, display_name="Tech Presenter", primary_role="Software Engineer & Tech Presenter", focus_track="tech_storytelling", experience_level="intermediate", target_wpm_min=125, target_wpm_max=155, max_filler_rate=2.0, min_eye_contact=0.70, daily_minutes_goal=15, weaknesses=["filler_words", "eye_contact"], speaking_goal_statement="Become a confident, articulate, engaging technology presenter through daily camera practice.", curriculum_start_date=date.today(), ) db.add(profile) db.commit() db.refresh(profile) return profile def serialize_profile(profile: models.PresenterProfile) -> dict[str, Any]: return { "id": profile.id, "display_name": profile.display_name, "primary_role": profile.primary_role, "focus_track": profile.focus_track, "focus_track_label": FOCUS_TRACK_LABELS.get(profile.focus_track, profile.focus_track), "experience_level": profile.experience_level, "target_wpm_min": profile.target_wpm_min, "target_wpm_max": profile.target_wpm_max, "max_filler_rate": profile.max_filler_rate, "min_eye_contact": profile.min_eye_contact, "daily_minutes_goal": profile.daily_minutes_goal, "weaknesses": profile.weaknesses if isinstance(profile.weaknesses, list) else [], "speaking_goal_statement": profile.speaking_goal_statement, "curriculum_start_date": profile.curriculum_start_date.isoformat(), } def _personalize_day_tip(day_entry: dict[str, Any], profile: models.PresenterProfile) -> str: weaknesses = set(profile.weaknesses if isinstance(profile.weaknesses, list) else []) tips: list[str] = [] if "filler_words" in weaknesses: tips.append(f"Keep fillers under {profile.max_filler_rate:.1f}/min by pausing silently at paragraph breaks.") if "eye_contact" in weaknesses: tips.append(f"Aim for {int(profile.min_eye_contact * 100)}%+ lens contact using top-of-frame teleprompter cues.") if "rushing_pace" in weaknesses: tips.append(f"Hold pace inside your {profile.target_wpm_min}–{profile.target_wpm_max} WPM target zone.") if "monotone_delivery" in weaknesses: tips.append("Emphasize contrast words ('however', 'suddenly', numbers) with deliberate pitch lift.") if "rambling_explanations" in weaknesses: tips.append("Land each bullet cue in 2–3 crisp sentences before moving to the next point.") track_note = { "tech_storytelling": "Frame this take like a high-retention creator segment for curious builders.", "keynote_clarity": "Project calm stage authority with clean architectural signposts.", "camera_confidence": "Prioritize relaxed shoulders, warm facial expression, and unhurried breaths.", "executive_pitch": "Lead with business & user impact in your opening sentence.", }.get(profile.focus_track, "") combined = " ".join(([track_note] + tips[:2])).strip() return combined or f"Target {profile.target_wpm_min}–{profile.target_wpm_max} WPM as a {profile.primary_role}." def record_curriculum_completion( db: Session, user_id: int, day_number: int, session_id: int | None = None, score: float | None = None, reflection_notes: str | None = None, ) -> models.CurriculumDayCompletion: if day_number < 1 or day_number > 30: raise ValueError("day_number must be between 1 and 30") row = ( db.query(models.CurriculumDayCompletion) .filter( models.CurriculumDayCompletion.user_id == user_id, models.CurriculumDayCompletion.day_number == day_number, ) .first() ) numeric_score = round(float(score or 0), 1) if row is None: row = models.CurriculumDayCompletion( user_id=user_id, day_number=day_number, completed_session_id=session_id, best_score=numeric_score, attempts_count=1, reflection_notes=reflection_notes, completed_at=datetime.utcnow(), ) db.add(row) else: row.attempts_count = (row.attempts_count or 1) + (1 if session_id else 0) if session_id is not None: row.completed_session_id = session_id if score is not None and numeric_score >= (row.best_score or 0): row.best_score = numeric_score if reflection_notes is not None: row.reflection_notes = reflection_notes row.updated_at = datetime.utcnow() db.commit() db.refresh(row) return row def get_curriculum_plan(db: Session, user_id: int) -> dict[str, Any]: profile = get_or_create_profile(db, user_id) completions = ( db.query(models.CurriculumDayCompletion) .filter(models.CurriculumDayCompletion.user_id == user_id) .all() ) by_day = {row.day_number: row for row in completions} completed_count = len(by_day) recommended_day = 1 for d in range(1, 31): if d not in by_day: recommended_day = d break else: recommended_day = 30 days_out: list[dict[str, Any]] = [] for entry in CURRICULUM_DAYS: day_num = entry["day"] comp = by_day.get(day_num) tip = _personalize_day_tip(entry, profile) dur_sec = int(entry.get("duration_sec", 90)) success_str = ( f"{profile.target_wpm_min}–{profile.target_wpm_max} WPM · " f"≤ {profile.max_filler_rate:.1f} fillers/min · " f"≥ {int(profile.min_eye_contact * 100)}% lens eye-contact" ) days_out.append({ **entry, "week_title": entry.get("week_theme", f"Week {entry['week']}"), "focus_skill": entry.get("skill_focus", "Camera Presence"), "duration_min": max(5, round(dur_sec / 6)), "warmup": entry.get("warm_up", ""), "camera_challenge": entry.get("challenge", ""), "prompt": entry.get("challenge", ""), "bullet_cues": entry.get("outline_cues", []), "success_metric": success_str, "personalized_tip": tip, "completed": comp is not None, "is_recommended_today": day_num == recommended_day, "completed_session_id": comp.completed_session_id if comp else None, "best_score": comp.best_score if comp else None, "attempts_count": comp.attempts_count if comp else 0, "reflection_notes": (comp.reflection_notes or "") if comp else "", "completed_at": comp.completed_at.isoformat() if comp and comp.completed_at else None, "personalized_coach_tip": tip, "target_metrics": { "wpm_min": profile.target_wpm_min, "wpm_max": profile.target_wpm_max, "max_filler_rate": profile.max_filler_rate, "min_eye_contact_pct": int(profile.min_eye_contact * 100), }, }) avg_best_score = ( round(sum(c.best_score for c in completions) / len(completions), 1) if completions else 0.0 ) week_defs = [ (1, "Camera Presence & Vocal Foundation", "Build relaxed camera eye-line, steady vocal pace, and silent pauses instead of filler words."), (2, "Structuring Technical Ideas", "Turn complex architectures, APIs, and tradeoffs into crisp 3-beat explanations."), (3, "Tech News & Builder Storytelling", "Synthesize live industry shifts into engaging 60s briefings, analogies, and hot takes."), (4, "Executive Demos, Q&A & Keynote Polish", "Deliver high-stakes product demos, incident updates, and conference-grade talks."), ] weeks_out = [] for wk_num, wk_title, wk_theme in week_defs: wk_days = [d for d in days_out if d["week"] == wk_num] weeks_out.append({ "week": wk_num, "title": wk_title, "theme": wk_theme, "completed_count": sum(1 for d in wk_days if d["completed"]), "total_count": len(wk_days), }) today_mission = next((d for d in days_out if d["day"] == recommended_day), days_out[0]) return { "profile": serialize_profile(profile), "summary": { "total_days": 30, "completed_days": completed_count, "completion_pct": round((completed_count / 30) * 100, 1), "recommended_day": recommended_day, "current_week": today_mission["week"], "avg_completed_score": avg_best_score, }, "weeks": weeks_out, "today_mission": today_mission, "days": days_out, } def get_personalized_exercises(db: Session, user_id: int) -> dict[str, Any]: profile = get_or_create_profile(db, user_id) recent_metrics = ( db.query(models.SessionMetrics) .filter(models.SessionMetrics.user_id == user_id) .order_by(models.SessionMetrics.recorded_at.desc()) .limit(8) .all() ) targeted: list[dict[str, Any]] = [] weaknesses = set(profile.weaknesses if isinstance(profile.weaknesses, list) else []) avg_wpm = ( round(sum(m.wpm for m in recent_metrics) / len(recent_metrics), 1) if recent_metrics else None ) avg_filler_rate = ( round(sum(m.filler_rate for m in recent_metrics) / len(recent_metrics), 2) if recent_metrics else None ) eye_vals = [m.eye_contact_score for m in recent_metrics if m.eye_contact_score is not None] avg_eye = round(sum(eye_vals) / len(eye_vals), 2) if eye_vals else None avg_vocab = ( round(sum(m.vocabulary_density for m in recent_metrics) / len(recent_metrics), 3) if recent_metrics else None ) # Top filler words across recent sessions filler_totals: dict[str, int] = {} for m in recent_metrics: if isinstance(m.filler_breakdown, dict): for word, count in m.filler_breakdown.items(): filler_totals[str(word)] = filler_totals.get(str(word), 0) + int(count or 0) top_filler_words = [w for w, _ in sorted(filler_totals.items(), key=lambda x: x[1], reverse=True)[:3]] # 1. Filler-targeted drill if (avg_filler_rate is not None and avg_filler_rate > profile.max_filler_rate) or "filler_words" in weaknesses: reason = ( f"Recent filler rate is {avg_filler_rate}/min (target ≤ {profile.max_filler_rate}/min)" + (f" — top fillers: {', '.join(top_filler_words)}." if top_filler_words else ".") if avg_filler_rate is not None else "Selected in your presenter profile priority areas." ) targeted.append({ "id": "targeted-filler-pause", "priority": "high", "focus_area": "Filler Elimination", "title": "Silent Beat-Pause Replacement Drill", "why_recommended": reason, "duration_sec": 75, "mode": "Interview", "goal": "Reduce fillers", "prompt": "Explain a technical tradeoff you made recently in 75 seconds. Every time a clause ends—or you feel a filler word forming—close your lips for 1 beat before continuing.", "teleprompter_script": ( "Today I am practicing clean transitions without filler words.\n\n" "First, here is the engineering problem we needed to solve. [Pause 1s]\n\n" "Second, here is the tradeoff we chose and what we deliberately left out. [Pause 1s]\n\n" "Therefore, the system stayed simple to operate and fast to ship." ), "outline_cues": [ "State the problem cleanly -> [1s silent breath]", "State the chosen approach -> [1s silent breath]", "State the measurable result -> hold lens contact", ], "target_keywords": ["first", "second", "therefore"], }) # 2. Pace-targeted drill if ( (avg_wpm is not None and (avg_wpm > profile.target_wpm_max or (0 < avg_wpm < profile.target_wpm_min))) or "rushing_pace" in weaknesses ): if avg_wpm is not None and avg_wpm > profile.target_wpm_max: reason = f"Your recent pace averaged {avg_wpm} WPM (above your {profile.target_wpm_min}–{profile.target_wpm_max} WPM target zone)." drill_title = "140 WPM Unhurried Keynote Pacing Drill" elif avg_wpm is not None and 0 < avg_wpm < profile.target_wpm_min: reason = f"Your recent pace averaged {avg_wpm} WPM (below your {profile.target_wpm_min}–{profile.target_wpm_max} WPM target zone)." drill_title = "Crisp Momentum & Energy Cadence Drill" else: reason = "Selected in your presenter profile to lock in steady keynote cadence." drill_title = "140 WPM Keynote Cadence Calibration" targeted.append({ "id": "targeted-wpm-calibration", "priority": "high", "focus_area": "Speaking Pace", "title": drill_title, "why_recommended": reason, "duration_sec": 60, "mode": "Reading", "goal": "Improve pace", "prompt": f"Use Auto-Scroll Teleprompter at 1.0x speed to deliver this 140-word tech passage in ~60 seconds ({profile.target_wpm_min}–{profile.target_wpm_max} WPM).", "teleprompter_script": ( "Great technical presenters control time rather than letting nervous adrenaline dictate their speed.\n\n" "When we rush through architecture diagrams or live demos, listeners miss the single insight that makes everything click.\n\n" "Instead, anchor your voice at a steady conversational rhythm. First, state your headline clearly. Second, illustrate it with one concrete example. Third, pause before your takeaway.\n\n" "Notice how much more authoritative your voice sounds when every sentence has room to land." ), "outline_cues": [ "0:00–0:15 Steady opening headline", "0:15–0:45 First, Second, Third points at even tempo", "0:45–1:00 Unhurried closing takeaway", ], "target_keywords": ["first", "second", "third", "rhythm"], }) # 3. Eye-contact targeted drill if (avg_eye is not None and avg_eye < profile.min_eye_contact) or "eye_contact" in weaknesses: reason = ( f"Recent camera lens eye contact averaged {int(avg_eye * 100)}% (target ≥ {int(profile.min_eye_contact * 100)}%)." if avg_eye is not None else "Selected in your presenter profile to strengthen direct camera connection." ) targeted.append({ "id": "targeted-lens-anchor", "priority": "medium", "focus_area": "Camera Eye Contact", "title": "Top-of-Frame Cue-Card Lens Anchor", "why_recommended": reason, "duration_sec": 60, "mode": "Storytelling", "goal": "Stronger eye contact", "prompt": "Speak from 3 short cue bullets in Cue-Card Teleprompter mode while keeping your gaze inside the top lens guide for at least 75% of the recording.", "teleprompter_script": ( "Speak naturally to the lens using 3 quick glances max:\n" "• Hook: Why developer experience makes or breaks adoption.\n" "• Story: A tool you loved within 5 minutes of installing.\n" "• Takeaway: One friction point you want to delete from your own project." ), "outline_cues": [ "Why DX drives adoption (eyes locked on lens)", "5-minute 'aha' story with a favorite tool", "One friction point to delete this week", ], "target_keywords": ["developer", "experience", "adoption"], }) # 4. Storytelling & structure drill (always ensure at least 2 targeted drills) if len(targeted) < 2 or "rambling_explanations" in weaknesses or (avg_vocab is not None and avg_vocab < 0.55): targeted.append({ "id": "targeted-hook-mechanism-impact", "priority": "medium", "focus_area": "Concise Tech Storytelling", "title": "Hook → Mechanism → Impact 90s Builder Drill", "why_recommended": "Builds tight narrative discipline so complex technical ideas land in 90 seconds without rambling.", "duration_sec": 90, "mode": "Pitch", "goal": "Improve pace", "prompt": "Pick any feature or engineering concept and explain it in strict 30-second blocks: (1) Problem Hook, (2) How It Works Under the Hood, (3) Measurable Impact.", "teleprompter_script": ( "Here is the problem most teams hit as soon as their app grows past its first thousand users.\n\n" "Under the hood, the bottleneck happens because every page reload repeats expensive queries.\n\n" "By introducing a lightweight cache invalidation strategy, response times drop from seconds to milliseconds—and infrastructure bills stay predictable." ), "outline_cues": [ "0:00–0:30 Problem Hook: What breaks at scale", "0:30–1:00 Mechanism: Why it happens & how the fix works", "1:00–1:30 Impact: Speed + cost + user delight", ], "target_keywords": ["problem", "because", "strategy", "milliseconds"], }) normalized_targeted = [ { **item, "target_metric": item.get("focus_area", "Presenter Delivery"), "duration_seconds": item.get("duration_sec", 75), "bullet_cues": item.get("outline_cues", []), } for item in targeted ] normalized_warmups = [ { **wu, "duration_seconds": wu.get("duration_sec", 60), "instructions": " ".join(wu.get("steps", [])), "script": wu.get("read_aloud_text", ""), } for wu in DAILY_WARMUPS ] normalized_challenges = [ { **ch, "duration_seconds": ch.get("duration_sec", 90), "difficulty": ch.get("badge", "Challenge"), "focus": ch.get("target_metric", ch.get("goal", "Clarity")), "teleprompter_script": "\n\n".join(ch.get("outline_cues", [])), "bullet_cues": ch.get("outline_cues", []), } for ch in CAMERA_CHALLENGES ] return { "diagnostic_snapshot": { "sessions_analyzed": len(recent_metrics), "avg_wpm": avg_wpm, "avg_filler_rate": avg_filler_rate, "avg_eye_contact_pct": int(avg_eye * 100) if avg_eye is not None else None, "top_filler_words": top_filler_words, }, "recent_averages": { "session_count": len(recent_metrics), "avg_wpm": avg_wpm or 0, "avg_filler_rate": avg_filler_rate or 0, "avg_eye_contact_pct": int(avg_eye * 100) if avg_eye is not None else 0, "avg_delivery_score": round(sum(m.delivery_score for m in recent_metrics) / len(recent_metrics), 1) if recent_metrics else 0, "avg_overall_score": round(sum(m.overall_score for m in recent_metrics) / len(recent_metrics), 1) if recent_metrics else 0, }, "targeted_exercises": normalized_targeted, "daily_warmups": normalized_warmups, "camera_challenges": normalized_challenges, }