Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 10x 10x 10x 10x 10x 10x 10x 1x 1x 1x 1x 1x 1x | /**
* Shared session-fact extractors for song share surfaces.
*
* Factored out of `app/observe/[token]/opengraph-image.tsx` so the OG image,
* the public `/song/[code]` page, and the lyric annotation engine all derive
* session facts from one place (never fork).
*
* These are pure helpers over a session plan's `parts` and a session song's
* `promptInput.currentSession` — safe to call from server components, route
* handlers, and `next/og` images.
*/
/** Subset of `SongPromptInput.currentSession` used across share surfaces. */
export interface SessionStats {
accuracy: number
problemsDone: number
problemsTotal: number
bestCorrectStreak: number
partTypes: string[]
durationMinutes: number
skillsPracticed: string[]
}
export interface SessionProblem {
terms: number[]
answer: number
}
/** Format a skill key like "basic.directAddition" into "Direct Addition". */
export function formatSkill(skill: string): string {
const name = skill.includes('.') ? skill.split('.').pop()! : skill
return name
.replace(/([A-Z])/g, ' $1')
.replace(/^./, (s) => s.toUpperCase())
.replace(/^\+/, 'Plus ')
.trim()
}
/** Extract sample problems from session plan `parts`. */
export function extractProblems(parts: unknown): SessionProblem[] {
if (!Array.isArray(parts)) return []
const problems: SessionProblem[] = []
for (const part of parts) {
if (part?.slots && Array.isArray(part.slots)) {
for (const slot of part.slots) {
if (slot?.problem?.terms && slot.problem.answer != null) {
problems.push({ terms: slot.problem.terms, answer: slot.problem.answer })
}
}
}
}
return problems
}
/** Format a problem as a string like "13 + 11 + 10 = 34". */
export function formatProblem(p: SessionProblem): string {
return `${p.terms.join(' + ')} = ${p.answer}`
}
|