All files / web/src/components/toys/coordinate-plane/wordProblems frames.ts

100% Statements 51/51
92.3% Branches 12/13
100% Functions 2/2
100% Lines 51/51

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 521x 1x 1x 1x 1x 1x 1x 1x 1x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 182x 1x 1x 1x 180x 180x 180x 180x 1x 1x 1x 1x 1x 1x 316x 316x 316x 1x 1x 315x 315x  
import type { SemanticFrame, RatePair, Scenario } from './types'
import { RATE_PAIR_REGISTRY } from './ratePairs'
import { SCENARIOS } from './scenarios'
 
/**
 * Compose a RatePair and Scenario into a SemanticFrame.
 * The frame ID is `${pair.id}:${scenario.id}`.
 */
export function buildFrame(pair: RatePair, scenario: Scenario): SemanticFrame {
  return {
    id: `${pair.id}:${scenario.id}`,
    category: pair.category,
    xNoun: scenario.xNoun ?? pair.xNoun,
    yNoun: scenario.yNoun ?? pair.yNoun,
    rateVerb: scenario.rateVerb ?? pair.rateVerb,
    xUnit: scenario.xUnit ?? pair.xUnit,
    yUnit: scenario.yUnit ?? pair.yUnit,
    xUnitPosition: pair.xUnitPosition,
    yUnitPosition: pair.yUnitPosition,
    xRole: pair.xRole,
    setupPhrases: scenario.setupPhrases,
    subjects: scenario.subjects,
    solveForXQuestions: scenario.solveForXQuestions,
    emoji: scenario.emoji,
    supportedLevels: scenario.supportedLevels,
    slopeRange: scenario.slopeRange,
    interceptRange: scenario.interceptRange,
    xRange: scenario.xRange,
    yRange: scenario.yRange,
  }
}
 
/** All available semantic frames (composed from rate pairs × scenarios) */
export const FRAMES: SemanticFrame[] = SCENARIOS.map((scenario) => {
  const pair = RATE_PAIR_REGISTRY.get(scenario.ratePairId)
  if (!pair) throw new Error(`Unknown ratePairId "${scenario.ratePairId}"`)
  return buildFrame(pair, scenario)
})
 
/** Registry: look up a frame by id */
export const FRAME_REGISTRY = new Map<string, SemanticFrame>(FRAMES.map((f) => [f.id, f]))
 
/** Get frames that support a given difficulty level */
export function framesForLevel(level: number): SemanticFrame[] {
  const frames = FRAMES.filter((f) => f.supportedLevels.includes(level as 1 | 2 | 3 | 4 | 5))
  // Level 5 falls back to level 3 frames if none explicitly support it
  if (frames.length === 0 && level === 5) {
    return FRAMES.filter((f) => f.supportedLevels.includes(3))
  }
  return frames
}