All files / web/src/components/practice partTransitionMessages.ts

0% Statements 0/170
0% Branches 0/1
0% Functions 0/1
0% Lines 0/170

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 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171                                                                                                                                                                                                                                                                                                                                                     
/**
 * Message pools for part transition screens
 *
 * Messages are organized by transition type and randomly selected
 * to keep daily practice sessions feeling fresh.
 */

import type { SessionPartType } from '@/db/schema/session-plans'

// ============================================================================
// Types
// ============================================================================

export interface TransitionMessage {
  /** Main headline text */
  headline: string
  /** Optional subtitle with additional instruction */
  subtitle?: string
}

export type TransitionType =
  | 'start-to-abacus'
  | 'abacus-to-visualization'
  | 'visualization-to-linear'
  | 'start-to-visualization'
  | 'start-to-linear'
  | 'abacus-to-linear'

// ============================================================================
// Message Pools
// ============================================================================

const START_TO_ABACUS_MESSAGES: TransitionMessage[] = [
  { headline: 'Get Ready!', subtitle: 'Grab your abacus' },
  { headline: "Let's Begin!", subtitle: 'Have your abacus ready' },
  { headline: 'Abacus Time', subtitle: 'Get your beads ready' },
]

const ABACUS_TO_VISUALIZATION_MESSAGES: TransitionMessage[] = [
  { headline: 'Mental Math Time!', subtitle: 'Put your abacus aside' },
  {
    headline: 'Visualization Mode',
    subtitle: 'Picture the beads in your mind',
  },
  { headline: 'Abacus Break', subtitle: 'Set it down gently' },
  { headline: 'Mind Over Beads', subtitle: 'Time to imagine' },
  { headline: 'Close Your Eyes...', subtitle: 'See the beads in your head' },
]

const VISUALIZATION_TO_LINEAR_MESSAGES: TransitionMessage[] = [
  { headline: 'Equation Mode!', subtitle: 'Same math, different look' },
  { headline: 'Reading Problems', subtitle: 'Like a math sentence' },
  { headline: 'Linear Style', subtitle: 'Left to right' },
  { headline: 'Number Sentences', subtitle: 'Quick mental math' },
]

const START_TO_VISUALIZATION_MESSAGES: TransitionMessage[] = [
  { headline: 'Mental Math!', subtitle: 'No abacus needed today' },
  { headline: 'Visualization Time', subtitle: 'Picture the beads' },
]

const START_TO_LINEAR_MESSAGES: TransitionMessage[] = [
  { headline: 'Quick Math!', subtitle: 'Solve these equations' },
  { headline: "Let's Go!", subtitle: 'Number sentences ahead' },
]

const ABACUS_TO_LINEAR_MESSAGES: TransitionMessage[] = [
  { headline: 'Equation Time!', subtitle: 'Put your abacus away' },
  { headline: 'Linear Mode', subtitle: 'No more beads for now' },
]

// ============================================================================
// Message Selection
// ============================================================================

/**
 * Get the transition type based on previous and next part types
 */
export function getTransitionType(
  previousPartType: SessionPartType | null,
  nextPartType: SessionPartType
): TransitionType {
  if (previousPartType === null) {
    // Session start
    switch (nextPartType) {
      case 'abacus':
        return 'start-to-abacus'
      case 'visualization':
        return 'start-to-visualization'
      case 'linear':
        return 'start-to-linear'
    }
  }

  if (previousPartType === 'abacus' && nextPartType === 'visualization') {
    return 'abacus-to-visualization'
  }
  if (previousPartType === 'visualization' && nextPartType === 'linear') {
    return 'visualization-to-linear'
  }
  if (previousPartType === 'abacus' && nextPartType === 'linear') {
    return 'abacus-to-linear'
  }

  // Fallback (shouldn't happen in normal flow)
  return 'visualization-to-linear'
}

/**
 * Get the message pool for a transition type
 */
function getMessagePool(transitionType: TransitionType): TransitionMessage[] {
  switch (transitionType) {
    case 'start-to-abacus':
      return START_TO_ABACUS_MESSAGES
    case 'abacus-to-visualization':
      return ABACUS_TO_VISUALIZATION_MESSAGES
    case 'visualization-to-linear':
      return VISUALIZATION_TO_LINEAR_MESSAGES
    case 'start-to-visualization':
      return START_TO_VISUALIZATION_MESSAGES
    case 'start-to-linear':
      return START_TO_LINEAR_MESSAGES
    case 'abacus-to-linear':
      return ABACUS_TO_LINEAR_MESSAGES
  }
}

/**
 * Select a random message for a transition
 *
 * Uses a simple random selection. For a deterministic selection
 * (e.g., based on session ID), pass a seed.
 */
export function selectTransitionMessage(
  previousPartType: SessionPartType | null,
  nextPartType: SessionPartType,
  seed?: number
): TransitionMessage {
  const transitionType = getTransitionType(previousPartType, nextPartType)
  const pool = getMessagePool(transitionType)

  // Use seed if provided, otherwise random
  const index =
    seed !== undefined ? Math.abs(seed) % pool.length : Math.floor(Math.random() * pool.length)

  return pool[index]
}

/**
 * Check if a transition requires putting away the abacus
 */
export function requiresAbacusPutAway(
  previousPartType: SessionPartType | null,
  nextPartType: SessionPartType
): boolean {
  if (previousPartType === null) return false
  return previousPartType === 'abacus' && nextPartType !== 'abacus'
}

/**
 * Check if a transition requires getting the abacus
 */
export function requiresAbacusPickUp(
  previousPartType: SessionPartType | null,
  nextPartType: SessionPartType
): boolean {
  if (previousPartType === null) return nextPartType === 'abacus'
  return previousPartType !== 'abacus' && nextPartType === 'abacus'
}