All files / web/src/arcade-games/type-racer-jr index.ts

78.43% Statements 80/102
100% Branches 0/0
0% Functions 0/1
78.43% Lines 80/102

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 1031x 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 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 1x 1x 1x 1x 1x 1x                                             1x 1x 1x 1x 1x 1x 1x 1x 1x  
/**
 * Type Racer Jr. - Game Definition
 *
 * A typing game for young learners. Kids type words letter-by-letter,
 * starting with tiny words (cat, dog, sun) and progressing to bigger ones.
 */
 
import { defineGame, getGameTheme } from '@/lib/arcade/game-sdk'
import type { GameManifest } from '@/lib/arcade/game-sdk'
import { TypeRacerGame } from './components/TypeRacerGame'
import { TypeRacerJrProvider } from './Provider'
import type { TypeRacerJrConfig, TypeRacerJrMove, TypeRacerJrState } from './types'
import { typeRacerJrValidator } from './Validator'
 
const manifest: GameManifest = {
  name: 'type-racer-jr',
  displayName: 'Type Racer Jr.',
  icon: '⌨️',
  description: 'Type words letter by letter to earn stars',
  longDescription:
    'Learn to type by spelling words one letter at a time! ' +
    'Start with tiny words like "cat" and "dog", then progress to bigger words. ' +
    'Earn stars for speed and accuracy!',
  maxPlayers: 1,
  difficulty: 'Beginner',
  chips: ['⌨️ Typing', '⭐ Stars', '📚 Learning'],
  ...getGameTheme('orange'),
  available: true,
  practiceBreakReady: true,
  practiceBreakConfig: {
    suggestedConfig: {
      gameMode: 'free-play',
      startingDifficulty: 'level1',
      wordCount: 5,
      timeLimit: null,
    },
    lockedFields: ['gameMode'],
    minDurationMinutes: 1,
    maxDurationMinutes: 5,
    difficultyPresets: {
      easy: {
        startingDifficulty: 'level1',
        wordCount: 5,
      },
      medium: {
        startingDifficulty: 'level1',
        wordCount: 8,
      },
      hard: {
        startingDifficulty: 'level2',
        wordCount: 10,
      },
    },
  },
  resultsConfig: {
    supportsResults: true,
    resultsDisplayDurationMs: 5000,
    scoreboardCategory: 'speed',
  },
  coPlay: { mode: 'none' },
}
 
const defaultConfig: TypeRacerJrConfig = {
  gameMode: 'free-play',
  timeLimit: null,
  startingDifficulty: 'level1',
  wordCount: 5,
  keyboardLayout: 'qwerty',
  showVirtualKeyboard: false,
}
 
function validateTypeRacerJrConfig(config: unknown): config is TypeRacerJrConfig {
  if (typeof config !== 'object' || config === null) return false
  const c = config as Record<string, unknown>

  if (!('gameMode' in c) || !['free-play', 'beat-the-clock'].includes(c.gameMode as string)) {
    return false
  }
  if (
    !('startingDifficulty' in c) ||
    !['level1', 'level2', 'level3'].includes(c.startingDifficulty as string)
  ) {
    return false
  }
  if ('timeLimit' in c && c.timeLimit !== null && typeof c.timeLimit !== 'number') {
    return false
  }
  if ('wordCount' in c && c.wordCount !== null && typeof c.wordCount !== 'number') {
    return false
  }

  return true
}
 
export const typeRacerJrGame = defineGame<TypeRacerJrConfig, TypeRacerJrState, TypeRacerJrMove>({
  manifest,
  Provider: TypeRacerJrProvider,
  GameComponent: TypeRacerGame,
  validator: typeRacerJrValidator,
  defaultConfig,
  validateConfig: validateTypeRacerJrConfig,
})