Download src/lib/tuition/teachLessonNotes.ts from asnannp/DocDoeAI: direct link, hf CLI and curl.
- Browser
- Download file 3.97 kB
-
https://huggingface.co/spaces/asnannp/DocDoeAI/resolve/main/src/lib/tuition/teachLessonNotes.ts
- Command line
-
hf download hf://spaces/asnannp/DocDoeAI/src/lib/tuition/teachLessonNotes.ts
-
curl -L -o teachLessonNotes.ts https://huggingface.co/spaces/asnannp/DocDoeAI/resolve/main/src/lib/tuition/teachLessonNotes.ts
3.97 kB
| export type TeachLessonSection = { | |
| id: string; | |
| title: string; | |
| markdown: string; | |
| boardPoints?: string[]; | |
| }; | |
| export type TeachLessonCheckpoint = { | |
| prompt: string; | |
| answer: string; | |
| explanation: string; | |
| }; | |
| export type TeachLessonNotes = { | |
| chapterId: string; | |
| missionId: string; | |
| title: string; | |
| method: string; | |
| goals: string[]; | |
| sections: TeachLessonSection[]; | |
| /** Chapter notebooks are not evidence that every mission is curated. */ | |
| scope?: "chapter" | "mission"; | |
| /** Explicit authored section identities, never inferred from title similarity. */ | |
| missionSectionIds?: Record<string, string[]>; | |
| aliases?: string[]; | |
| recall?: { | |
| question: string; | |
| expectedIdea: string; | |
| correctFeedback?: string; | |
| incorrectFeedback?: string; | |
| }; | |
| practice?: { question: string; hint: string }; | |
| exam?: { | |
| question: string; | |
| answer: string; | |
| points: string[]; | |
| keywords: string[]; | |
| }; | |
| checkpoint?: TeachLessonCheckpoint[]; | |
| }; | |
| export const TEACH_METHOD = | |
| "Learn → Understand → Solve → Exam Answer → Weakness Fix"; | |
| const NOTES: TeachLessonNotes[] = []; | |
| export function registerTeachLessonNotes(notes: TeachLessonNotes) { | |
| for (const [mission, ids] of Object.entries(notes.missionSectionIds ?? {})) { | |
| if ( | |
| !mission.trim() || !ids.length || new Set(ids).size !== ids.length || | |
| ids.some((id) => notes.sections.filter((section) => section.id === id).length !== 1) | |
| ) { | |
| throw new Error(`Invalid teach section mapping: ${notes.chapterId}/${mission}`); | |
| } | |
| } | |
| NOTES.push(notes); | |
| } | |
| export function physicsTeachNotes( | |
| notes: Omit<TeachLessonNotes, "method" | "missionId"> & { missionId?: string }, | |
| ): TeachLessonNotes { | |
| const full: TeachLessonNotes = { | |
| missionId: "M1", | |
| method: TEACH_METHOD, | |
| scope: notes.missionId ? "mission" : "chapter", | |
| ...notes, | |
| }; | |
| registerTeachLessonNotes(full); | |
| return full; | |
| } | |
| export const mathTeachNotes = physicsTeachNotes; | |
| export const chemistryTeachNotes = physicsTeachNotes; | |
| export const historyTeachNotes = physicsTeachNotes; | |
| export const geographyTeachNotes = physicsTeachNotes; | |
| export const sslcTeachNotes = physicsTeachNotes; | |
| export function getTeachLessonNotes( | |
| chapterId: string | null | undefined, | |
| missionId?: string, | |
| ): TeachLessonNotes | null { | |
| if (!chapterId) return null; | |
| const id = chapterId.trim().toLowerCase(); | |
| const matches = NOTES.filter((notes) => { | |
| const ids = [notes.chapterId, ...(notes.aliases ?? [])].map((value) => | |
| value.toLowerCase(), | |
| ); | |
| return ids.includes(id); | |
| }); | |
| // Omitting the mission is an explicit chapter-notebook request. A lesson | |
| // always passes its mission and must never receive this broad fallback. | |
| if (missionId === undefined) { | |
| return matches.find((notes) => notes.scope === "chapter") ?? null; | |
| } | |
| const mission = missionId.trim().toUpperCase(); | |
| const exact = matches.find((notes) => notes.scope !== "chapter" | |
| && notes.missionId.toUpperCase() === mission); | |
| if (exact) return exact; | |
| const chapter = matches.find((notes) => notes.scope === "chapter" | |
| && notes.missionSectionIds?.[mission]); | |
| const ids = chapter?.missionSectionIds?.[mission]; | |
| if (process.env.DEBUG_FIX === "1") { | |
| console.debug("[FIX:mission-teach-scope]", { | |
| chapterId: id, missionId: mission, mapped: Boolean(ids), sectionCount: ids?.length ?? 0, | |
| }); | |
| } | |
| if (!chapter || !ids) return null; | |
| const sections = ids.map((sectionId) => chapter.sections.find((section) => section.id === sectionId)!); | |
| // Do not carry chapter-wide practice, recall or exam prompts into a mission. | |
| return { | |
| chapterId: chapter.chapterId, missionId: mission, scope: "mission", | |
| title: `${chapter.title} · ${mission}`, method: chapter.method, | |
| goals: sections.map((section) => section.title), sections, | |
| }; | |
| } | |
| export function teachBeatTitles( | |
| notes: TeachLessonNotes | null | undefined, | |
| ): string[] { | |
| return notes?.sections.map((section) => section.title) ?? []; | |
| } | |