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 60 61 62 63 64 65 66 67 68 69 70 71 | 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 1x 1x 5541x 5541x 5541x 5541x 5541x 5541x 5541x 1x 1x 1x 1x 1x 1x 1x 1x 2601x 762x 762x 762x 762x 762x 1839x 2601x 628x 628x 1x 1x 1x 1x 1x 1x 940x 940x 940x 940x 940x 940x 940x | import type { SemanticFrame, SubjectEntry } from './types'
import { capitalize } from './inflect'
/** A character that can star in a word problem */
export interface Character {
name: string
pronoun: 'she' | 'he' | 'they'
possessive: 'her' | 'his' | 'their'
}
export const CHARACTERS: Character[] = [
{ name: 'Sonia', pronoun: 'she', possessive: 'her' },
{ name: 'Marcus', pronoun: 'he', possessive: 'his' },
{ name: 'Priya', pronoun: 'she', possessive: 'her' },
{ name: 'Kai', pronoun: 'he', possessive: 'his' },
{ name: 'Amara', pronoun: 'she', possessive: 'her' },
{ name: 'Leo', pronoun: 'he', possessive: 'his' },
{ name: 'Mei', pronoun: 'she', possessive: 'her' },
{ name: 'Diego', pronoun: 'he', possessive: 'his' },
{ name: 'Zara', pronoun: 'she', possessive: 'her' },
{ name: 'Noah', pronoun: 'he', possessive: 'his' },
{ name: 'Aisha', pronoun: 'she', possessive: 'her' },
{ name: 'Ravi', pronoun: 'he', possessive: 'his' },
{ name: 'Luna', pronoun: 'she', possessive: 'her' },
{ name: 'Ethan', pronoun: 'he', possessive: 'his' },
{ name: 'Yuki', pronoun: 'they', possessive: 'their' },
]
/**
* Replace {name}, {pronoun}, {Pronoun}, {possessive}, {Possessive} in a string.
*/
export function resolveTemplate(text: string, character: Character): string {
return text
.replace(/\{name\}/g, character.name)
.replace(/\{pronoun\}/g, character.pronoun)
.replace(/\{Pronoun\}/g, capitalize(character.pronoun))
.replace(/\{possessive\}/g, character.possessive)
.replace(/\{Possessive\}/g, capitalize(character.possessive))
}
/**
* Resolve a subject entry's placeholders.
*
* - `{Pronoun}` subjects get conjugation auto-set: 'they' → 'base', else 'thirdPerson'.
* - All other subjects get simple template replacement with conjugation preserved.
*/
export function resolveSubject(subject: SubjectEntry, character: Character): SubjectEntry {
if (subject.phrase === '{Pronoun}') {
return {
phrase: capitalize(character.pronoun),
conjugation: character.pronoun === 'they' ? 'base' : 'thirdPerson',
}
}
const resolved = resolveTemplate(subject.phrase, character)
if (resolved === subject.phrase) return subject // no placeholders — return original
return { phrase: resolved, conjugation: subject.conjugation }
}
/**
* Resolve all character placeholders in a SemanticFrame.
* Returns a new frame — the original is not mutated.
*/
export function resolveCharacter(frame: SemanticFrame, character: Character): SemanticFrame {
return {
...frame,
setupPhrases: frame.setupPhrases.map((p) => resolveTemplate(p, character)),
subjects: frame.subjects.map((s) => resolveSubject(s, character)),
solveForXQuestions: frame.solveForXQuestions?.map((q) => resolveTemplate(q, character)),
}
}
|