import type { TuitionLessonSeed } from "./physicsLessonSeeds"; /** * A deterministic objective map for a curated lesson seed. * * The content author supplies the goal, explanation blocks, formulas, and * board-answer prompts. This function only gives those authored parts stable * identifiers so evidence can say exactly what it assessed. It does not ask an * AI to infer progress or invent a syllabus objective. */ export type LessonObjective = { id: string; statement: string; kind: "concept" | "formula" | "application" | "board_answer"; }; function stableObjectiveId(seed: TuitionLessonSeed, index: number): string { return `${seed.chapterId}:${seed.missionId}:OBJ${index + 1}`; } function explainableStatement(value: string): string { const trimmed = value.trim().replace(/[.]+$/, ""); if (!trimmed) return "Explain the source-backed lesson idea."; if (/^(explain|define|describe|compare|calculate|derive|write|identify|use|solve)\b/i.test(trimmed)) { return `${trimmed}.`; } if (/^master\b/i.test(trimmed)) return `${trimmed.replace(/^master\b/i, "Explain")}.`; if (/^understand\b/i.test(trimmed)) return `${trimmed.replace(/^understand\b/i, "Explain")}.`; return `Explain ${trimmed}.`; } function missionIdea(seed: TuitionLessonSeed): string { return seed.missionTitle.replace(/^M\d+\s*:\s*/i, "").trim() || seed.chapterTitle; } function isGenericBlockHeading(value: string): boolean { return /^(understanding|exam focus|remember|quick recap|key points?|in brief)\b/i.test(value.trim()); } export function objectivesForLessonSeed(seed: TuitionLessonSeed): LessonObjective[] { const statements: Array> = [ { kind: "concept", statement: explainableStatement(seed.goal) }, { kind: "concept", statement: `Explain the key idea in ${missionIdea(seed)}.` }, ]; for (const block of seed.teach.explanationBlocks.slice(0, 3)) { if (block.heading.trim() && !isGenericBlockHeading(block.heading)) { statements.push({ kind: "concept", statement: explainableStatement(block.heading) }); } } for (const formula of seed.formulas.slice(0, 2)) { if (formula.formula.trim()) { statements.push({ kind: "formula", statement: `Use ${formula.formula.trim()} with the correct symbols and units.`, }); } } if (seed.contentType === "numerical" || seed.quiz.some((question) => question.type === "numerical")) { statements.push({ kind: "application", statement: "Solve a similar application question with the method and final unit shown.", }); } const boardAnswer = seed.examAnswers[0]; if (boardAnswer) { statements.push({ kind: "board_answer", statement: `Write a concise ${boardAnswer.marks}-mark board answer using the required points.`, }); } const unique = new Map>(); for (const objective of statements) { const key = objective.statement.toLocaleLowerCase("en-IN"); if (!unique.has(key)) unique.set(key, objective); } return [...unique.values()].slice(0, 6).map((objective, index) => ({ ...objective, id: stableObjectiveId(seed, index), })); }