Skip to main content

Overview

CodeJam features multiple coding challenges (“games”) across different languages and difficulty levels. Each game has objectives, XP rewards, and player statistics.

Queries

getGameStats

Returns player count statistics for all games.
import { useQuery } from "convex/react";
import { api } from "@/convex/_generated/api";

const playerCounts = useQuery(api.games.getGameStats);
// Returns: { "syntax-smasher": 1234, "function-fury": 567, ... }
Returns: Record<string, number> An object mapping game IDs to the number of unique players who have played each game.
This aggregates all game_stats records. In production, this would use a separate counter table for scalability.

getGameMetadata

Returns detailed metadata for a specific game.
gameId
string
required
Game identifier (e.g., “syntax-smasher”, “function-fury”)
const game = useQuery(api.games.getGameMetadata, { 
  gameId: "syntax-smasher" 
});
Returns: GameMetadata

Objective Types

Each objective has:
id
string
Unique objective identifier
label
string
Human-readable objective description
type
string
Objective type: collection, streak, time, or bool
target
number
Target value to achieve (e.g., 5 for “Survive 5 Rounds”)

Available Games

Syntax Smasher

{
  title: 'Syntax Smasher',
  language: 'JavaScript',
  difficulty: 'Beginner',
  description: 'Race against time to fix broken syntax errors.',
  objectives: [
    { id: 'syntax', label: 'Survive 5 Rounds', type: 'collection', target: 5 },
    { id: 'streak', label: 'Maintain 5x Streak', type: 'streak', target: 5 },
    { id: 'clean', label: 'No Compilation Errors', type: 'bool', target: 1 }
  ],
  baseXp: 100
}

Syntax Smasher

Language: JavaScript
Difficulty: Beginner
XP Reward: 100
Fix syntax errors quickly to survive multiple rounds and maintain your streak.

Function Fury

{
  title: 'Function Fury',
  language: 'JavaScript',
  difficulty: 'Intermediate',
  description: 'Master higher-order functions and stubborn closures.',
  objectives: [
    { id: 'syntax', label: 'Fix Syntax Errors', type: 'collection', target: 1 },
    { id: 'streak', label: 'Maintain 3x Streak', type: 'streak', target: 3 },
    { id: 'speed', label: 'Complete under 60s', type: 'time', target: 60 }
  ],
  baseXp: 150
}

Function Fury

Language: JavaScript
Difficulty: Intermediate
XP Reward: 150
Work with higher-order functions and closures under time pressure.

CSS Combat

{
  title: 'CSS Combat',
  language: 'CSS',
  difficulty: 'Advanced',
  description: 'Master flexbox and grid in a battle arena.',
  objectives: [
    { id: 'layout', label: 'Match Layout', type: 'bool', target: 1 },
    { id: 'streak', label: 'Perfect Alignment', type: 'streak', target: 1 },
  ],
  baseXp: 200
}

CSS Combat

Language: CSS
Difficulty: Advanced
XP Reward: 200
Master flexbox and CSS grid to match target layouts perfectly.

Logic Labyrinth

{
  title: 'Logic Labyrinth',
  language: 'Python',
  difficulty: 'Intermediate',
  description: 'Navigate the maze using boolean logic gates.',
  objectives: [
    { id: 'solve', label: 'Solve Maze', type: 'bool', target: 1 },
    { id: 'optimize', label: 'Optimize Path', type: 'bool', target: 1 }
  ],
  baseXp: 175
}

Logic Labyrinth

Language: Python
Difficulty: Intermediate
XP Reward: 175
Solve mazes using boolean logic and path optimization.

Algo Arena

{
  title: 'Algo Arena',
  language: 'C++',
  difficulty: 'Expert',
  description: 'Optimize memory usage in high-stakes sorting battles.',
  objectives: [
    { id: 'pass', label: 'Pass Unit Tests', type: 'bool', target: 1 },
    { id: 'memory', label: 'O(n) Memory', type: 'bool', target: 1 }
  ],
  baseXp: 300
}

Algo Arena

Language: C++
Difficulty: Expert
XP Reward: 300
High-stakes algorithmic challenges with memory optimization constraints.

Game Statistics Schema

Player statistics are stored in the game_stats table:
Statistics are indexed by userId and gameId for efficient lookups.

Example: Game Selection Screen

import { useQuery } from "convex/react";
import { api } from "@/convex/_generated/api";

const GAME_IDS = [
  'syntax-smasher',
  'function-fury',
  'css-combat',
  'logic-labyrinth',
  'algo-arena'
];

function GameBrowser() {
  const playerCounts = useQuery(api.games.getGameStats);
  
  return (
    <div className="game-grid">
      {GAME_IDS.map(gameId => {
        const game = useQuery(api.games.getGameMetadata, { gameId });
        if (!game) return null;
        
        return (
          <div key={gameId} className="game-card">
            <h3>{game.title}</h3>
            <p>{game.description}</p>
            <div>
              <span>{game.language}</span>
              <span>{game.difficulty}</span>
            </div>
            <p>{playerCounts?.[gameId] || 0} players</p>
            <p>{game.baseXp} XP</p>
            
            <h4>Objectives:</h4>
            <ul>
              {game.objectives.map(obj => (
                <li key={obj.id}>{obj.label}</li>
              ))}
            </ul>
          </div>
        );
      })}
    </div>
  );
}

Build docs developers (and LLMs) love