Skip to content

rsquared226/jeopaarathi

Repository files navigation

Jeop-Aarathi

A small real-time Jeopardy-style game built with Vue 3 + Vite on the frontend and AWS Amplify (AppSync + Lambda + DynamoDB) on the backend.

What this project is

Jeop-Aarathi is a TV-friendly, moderator-driven Jeopardy-style game for a single party or event. It focuses on:

  • High-contrast visual display for a room or projector.
  • Smooth, keyboard/mouse-driven control by the host.
  • Real-time buzzer experience for players on their phones.
  • Simple deployment via AWS Amplify with a single shared game state.

Questions are stored in DynamoDB and loaded via a GraphQL API; they are not checked into git.

Host Experience (Game Board)

  • Two-team scoreboard

    • “Autumn Orange” and “Sea Foam Green” teams.
    • Automatic score updates based on question values and answer correctness.
    • Negative scores are clearly displayed in red.
    • Direct inline editing: click a team’s score to correct it mid-game.
  • Jeopardy-style game board

    • 5×5 grid: 5 categories × values 200, 400, 600, 800, 1000.
    • Categories and questions are loaded from the backend via GraphQL and cached in the browser.
    • Value cells become disabled/“answered” after use, based on backend used flags.
    • After a host reload mid-game, already-used clues remain greyed out and cannot be clicked again.
  • Question modal & scoring flow

    • Full-screen modal that does not obscure the scoreboard at the top of the screen.
    • Phases:
      • Reading / buzz prep: clue is shown while buzzers are temporarily disabled. The host sees a configurable pre-buzz countdown bar ("Buzzers active in N…") before buzzers open.
      • First attempt: one team is locked in; host scores Correct or Wrong.
      • Re-buzz / opponent chance: the opposing team can steal. During the steal window, an inline “Decide to steal in N…” countdown bar replaces the Correct / Wrong / No Steal (Time Up) buttons; when the countdown finishes, those buttons reappear so the host can resolve the steal.
    • “Show Answer” toggle is available in the tally phases so the host can reveal or hide the intended answer.
    • A Reset Game control clears scores and question usage and returns the board to a fresh state for another round.
  • Timer controls

    • A small Timer Settings button in the top-right opens a popover that lets the host configure:
      • Clue read delay (seconds before buzzers open).
      • Buzzer lead time (how early to activate buzzers before the prep bar visually finishes).
      • Answer timer length (for each team’s answer).
      • Steal decision timer length (RE_BUZZ window).
      • Whether to play a short sound when a timer hits zero.

Buzzer Experience (Player Phones)

  • Players join by navigating to the buzzer URL with a ?mode=buzzer&team=team1|team2 query parameter.
  • Each phone shows:
    • A large team-colored BUZZ button when buzzers are active.
    • Clear status text, e.g.:
      • Host is reading the clue...
      • BUZZ / STEAL
      • Locked in! / Wrong answer...
      • Waiting for the next clue...
  • Buzzer logic is enforced on the backend:
    • Only one team can lock in at a time.
    • During a re-buzz window, the first team cannot buzz again; only the other team can steal.
    • Buzz attempts outside an active window are safely ignored.

Technical Overview

Architecture

  • Frontend

    • Vite + Vue 3 + TypeScript.
    • Tailwind CSS for styling.
    • Composition API (<script setup lang="ts">) used across components.
    • Two entrypoints in a single app:
      • Host view (App.vue) – scoreboard + board + question modal.
      • Buzzer view (TeamBuzzer.vue) – phone-friendly buzzer client.
  • Backend

    • AWS Amplify project with:
      • AppSync GraphQL API.
      • Lambda resolver (GameController) implementing all game logic.
      • DynamoDB tables for Question and GameState.

Game State Model

  • Central GameState record in DynamoDB, keyed by a fixed ID (e.g. CURRENT_GAME).
  • Key fields (simplified):
    • status: SELECTING_CLUE | CLUE_ACTIVE | BUZZER_ACTIVE | BUZZER_LOCKED | RE_BUZZ.
    • currentQuestionId, currentCategory, currentValue, currentClueText.
    • buzzedTeam: which backend team is currently locked in.
    • hasFirstAttemptedTeam: which team has already attempted this clue.
    • autumnOrangeScore, seaFoamGreenScore.
    • readDelayMs, clueActivatedAt, reBuzzWindowMs, reBuzzActivatedAt.

GraphQL Operations

  • Queries

    • getBoard: returns all questions (category, value, clue, answer, used).
    • getGameState: returns the current GameState.
  • Mutations (all routed to GameController Lambda)

    • selectClue(id: ID!, questionId: ID!): move to CLUE_ACTIVE and set the active question.
    • activateBuzzers(id: ID!): transition from CLUE_ACTIVE to BUZZER_ACTIVE.
    • buzz(id: ID!, teamId: TeamId!): lock in a team when buzzers are active.
    • submitAnswerResult(id: ID!, isCorrect: Boolean!): score the current answer and either end the clue or open a re-buzz window.
    • resetBuzzers(id: ID!): return to BUZZER_ACTIVE from BUZZER_LOCKED if needed.
    • abandonQuestion(id: ID!): exit a clue without marking it used, resetting to SELECTING_CLUE.
    • noSteal(id: ID!): end a clue in RE_BUZZ when no steal happens, marking the question as used.
    • resetGame(id: ID!): reset scores, game state, and question used flags.
  • Subscription

    • onGameStateChanged(id: ID!): pushes full GameState snapshots to host and buzzer clients whenever any of the above mutations run.

Frontend State Management

  • useGameApi.ts

    • Wraps Amplify API.graphql calls for all GraphQL queries, mutations, and subscriptions.
  • useGameState.ts

    • Holds a reactive gameState ref shared across host and buzzer views.
    • Subscribes to onGameStateChanged to keep clients in sync in real-time.
    • Exposes high-level methods: selectClue, activateBuzzers, buzzForTeam, submitAnswer, abandonQuestion, noSteal, resetGame.
  • useQuestions.ts + QuestionsRepository

    • Loads the full board from getBoard and validates structure.
    • Exposes reactive questions and categories to the host view.
    • Each question includes a used flag mirrored from DynamoDB so the board can grey out used cells even after reloads.

Local Board State & Reload Handling

  • Host App.vue maintains local UI state:
    • answeredCells: which board cells should be disabled.
    • currentCategory, currentValue, buzzedTeam, opponentTeam, modalPhase, showAnswer.
  • On first load, a small sync seeds answeredCells from backend used flags.
  • A watcher on gameState reconstructs the question modal after a reload based on the backend status and fields, so the host can safely refresh the page mid-question without desynchronizing the game.

Deployment

See AWS_DEPLOYMENT.md for step-by-step instructions to deploy the backend (Amplify) and frontend (Amplify Hosting or S3 + CloudFront) in your own AWS account.

Development

This repo contains both the Amplify backend and the Vue frontend.

Frontend (Vite dev server)

From frontend/:

npm install
npm run dev

Open the printed local URL (default http://localhost:5173/).

  • Host view (default): http://localhost:5173/
  • Buzzer view: http://localhost:5173/?mode=buzzer&team=team1 or team2

Backend (Amplify)

The backend is managed by the Amplify CLI.

  • Initialize / pull environment as needed:
amplify pull
  • After making schema or function changes:
amplify push

See the Amplify docs for environment setup (AWS credentials, region, etc.).

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published