This project is a comprehensive platform for creating, managing, and displaying gaming tournaments in various formats, including Single Elimination, Double Elimination, and Round Robin. It features a Go backend for API and logic, and a Next.js (React) frontend for user interaction and bracket visualization.
- Features
- Tech Stack
- Project Structure
- Setup and Installation
- Core Functionality
- Key Backend Components/Logic
- Key Frontend Components/Logic
- API Endpoints (Overview)
- Future Enhancements / TODO
- Contributing
- License
- User Authentication (assumed, context:
useAuth) - Tournament Creation: Specify name, game, description, format, dates, etc.
- Multiple Tournament Formats:
- Single Elimination
- Double Elimination
- Round Robin
- Swiss (basic placeholder)
- Participant Management: Add participants to tournaments before bracket generation.
- Automated Bracket Generation: Creates match schedules based on selected format and participants.
- Handles seeding and byes for elimination formats.
- Uses circle method for Round Robin.
- Score Reporting:
- Inline score editing for Round Robin matches.
- Modal/Popover score editing for Elimination bracket matches.
- Optimistic UI updates for a smoother user experience.
- Dynamic Bracket/Table Visualization:
- Interactive SVG-based elimination brackets (
DarkChallongeBracket.tsx). - Clear Round Robin standings and match lists (
RoundRobinTable.tsx). - Participant statistics tables for elimination formats.
- Interactive SVG-based elimination brackets (
- Real-time (or near real-time after refresh) updates to brackets and standings upon score entry.
- Clear visual distinction for match status, winners, and different bracket sections (e.g., Losers Bracket).
- Backend: Go
- Web Framework: Gin
- Database: PostgreSQL
- ORM/DB Layer:
database/sql - UUIDs:
github.com/google/uuid
- Frontend: Next.js (React)
- State Management: React Hooks (
useState,useEffect,useMemo,useCallback), Context API (useAuth) - Styling: Tailwind CSS (potentially with DaisyUI or similar component library for
btn,card, etc.) - Routing: Next.js App Router
- Icons: Heroicons (
@heroicons/react) - API Client: Custom fetch-based client (
src/lib/api/tournament.ts)
- State Management: React Hooks (
- Database: PostgreSQL
- Prerequisites: Go, PostgreSQL server.
- Clone the repository:
git clone https://github.com/cliffdoyle/gamer_world.git - Navigate to backend directory:
cd tournament-service - Database Setup:
- Create a PostgreSQL database.
- Run database migrations to create necessary tables (
tournaments,participants,matches). Ensure thematchestable includes:bracket_type VARCHAR(20)participant1_prereq_match_id UUID NULLparticipant2_prereq_match_id UUID NULLparticipant1_prereq_match_result_source VARCHAR(10) NULLparticipant2_prereq_match_result_source VARCHAR(10) NULL- And all other fields from
domain.Match.
- Configuration:
- Set up environment variables or a config file for:
- Database connection string (user, password, host, port, dbname)
- JWT secret
- Server port
- Set up environment variables or a config file for:
- Install Dependencies:
go mod tidy - Run the server:
go run cmd/server/main.go
- Prerequisites: Node.js, npm.
- Clone the repository:
git clone https://github.com/cliffdoyle/gamer_world.git - Navigate to frontend directory:
cd tournament-frontend - Install Dependencies:
npm installoryarn install- Ensure
@heroicons/reactandtailwind-scrollbar(if used) are installed.
- Ensure
- Configuration:
- Create a
.env.localfile in the root oftournament-frontend. - Add your backend API base URL:
NEXT_PUBLIC_API_BASE_URL=http://localhost:8082 #
src/lib/api/config.tsshould use this environment variable.
- Create a
- Run the development server:
npm run devoryarn dev - Open http://localhost:3000 in your browser.
- Ensure your PostgreSQL server is running.
- Create the tournament database if it doesn't exist.
- Apply the schema migrations to create tables:
tournaments,participants,matches.matchestable requires special attention to include all fields from the Godomain.Matchstruct, particularly thebracket_typeand the four prerequisite fields for TBD resolution (participant1_prereq_match_id,participant2_prereq_match_id,participant1_prereq_match_result_source,participant2_prereq_match_result_source).
- Users can create new tournaments, specifying essential details.
- Tournament status (
DRAFT,REGISTRATION,IN_PROGRESS,COMPLETED,CANCELLED) tracks its lifecycle.
- Participants can be added to tournaments during the
DRAFTorREGISTRATIONphase, before the bracket is generated and within registration deadlines. - The system checks against
maxParticipants.
- Triggered manually via the UI by an authorized user.
- Requires at least 2 participants.
- The Go backend's
bracketpackage contains distinct generators:SingleEliminationGenerator: Uses seeding (applyChallongeSeeding) and handles byes. Populates prerequisite match fields for accurate "Winner of Mx" display.DoubleEliminationGenerator:- Uses
generateWinnersBracketFromSingleElim(which itself calls the core SE logic) for the Winners Bracket. generateLosersBracketlogic determines how losers drop and are paired with advancing LB players, setting prerequisite fields (including_result_sourceas "LOSER" or "WINNER").generateFinalMatchescreates 1 or 2 Grand Final matches with correct prerequisite links from WB and LB finals.
- Uses
RoundRobinGenerator: Uses the circle method.SwissGenerator: Basic placeholder structure.
- Once generated, participants can no longer be added/removed.
- Managed through the
TournamentDetailPage(page.tsx). - Round Robin: Features inline editing directly on match cards via
RoundRobinTable.tsx. - Elimination (SE/DE): Uses a popover-style modal (
MatchScoreEditor.tsx) triggered by clicking a match (or an edit icon) in the SVG bracket (DarkChallongeBracket.tsx). - Uses optimistic UI updates for a responsive feel, then syncs with the backend.
- Backend
UpdateMatchScoreservice correctly determineswinner_id(ornilfor RR draws) andstatusbefore saving and advancing participants in elimination formats.
BracketRenderer.tsxconditionally renders the appropriate display component based on tournament format.DarkChallongeBracket.tsx:- Renders interactive SVG brackets for Single and Double Elimination.
- Dynamically calculates match positions and connector lines.
- Displays "Winner of Mx" / "Loser of Mx" for TBD slots if backend provides prerequisite data (
participantX_prereq_match_idandparticipantX_prereq_match_result_source). - Includes visual cues for editable matches.
RoundRobinTable.tsx:- Displays a clear standings table (Rank, MP, W, L, D, Pts).
- Lists matches grouped by round with scores.
EliminationStatsTable.tsx:- Provides a statistics table (MP, W, L, Pts) for participants in SE/DE tournaments.
Tournament,Participant,Matchstructs define the core data structures.Matchstruct includes crucial fields:bracket_type,loser_next_match_id,participantX_prereq_match_id, andparticipantX_prereq_match_result_source.- Enums for
TournamentFormat,TournamentStatus,MatchStatus,BracketType,PrereqSourceType.
- Handles all direct database interactions (CRUD operations) for
tournaments,participants, andmatchestables usingdatabase/sql. - Must be updated to read/write the new prerequisite fields in the
matchestable.
tournamentServiceorchestrates business logic.CreateTournament: Handles creation, setting initial status toDRAFTorREGISTRATION.AddParticipant: Adds a participant if rules allow.GenerateBracket: Calls the appropriate generator from thebracketpackage based ontournament.Format. Crucially updatesmatchesand ideally thetournament.status.UpdateMatchScore: The refined version correctly determineswinner_idbased on scores for all formats (nil for RR draws), updates match status, saves the match, and then handles participant advancement in elimination brackets based onnext_match_idandloser_next_match_id, ideally using prerequisite data for precise slotting.
SingleEliminationGenerator: Core logic (generateSingleEliminationInternal) setsNextMatchIDandParticipantXPrereqMatchID/Source("WINNER").DoubleEliminationGenerator:generateWinnersBracketFromSingleElim: Calls the core SE logic.generateLosersBracket: Complex logic to create LB structure. This part is critical and must accurately setLoserNextMatchIDon WB matches,NextMatchIDon LB matches, and the full set of prerequisite fields (IDandSourceas "WINNER" or "LOSER") for each slot in new LB matches.generateFinalMatches: Creates GF1 (and optional GF2) linking WB/LB finals and setting appropriate prerequisite data.
- Relies on helper functions for seeding (
applyChallongeSeeding) and byes.
- Fetches all data for a specific tournament (
tournament,participants,matches). - Manages UI state: loading, errors, modal visibility, inline editing state for RR.
- Handles user actions: adding participants, generating bracket, initiating score updates.
- Implements optimistic UI updates for score changes.
- Renders
EliminationStatsTableor delegates bracket/table display toBracketRenderer. - Controls the visibility and data for
MatchScoreEditor.
- A simple conditional renderer that chooses between
DarkChallongeBracket.tsx(for SE/DE) andRoundRobinTable.tsx. - Passes down necessary props, including callbacks for editing and inline editing state for RR.
- Renders SE/DE tournaments as an SVG.
- Layout Algorithm: Complex
useEffecthook calculates X/Y positions for each match, grouping them byui_bracket_section(WINNERS, LOSERS, GRAND_FINALS) to create distinct visual areas. Aims for compact, Challonge-like layout. - Connector Lines: Draws SVG
<path>elements between matches based onnext_match_idandloser_next_match_id, targeting correct P1/P2 slots using prerequisite data if available. - TBD Labels: Uses
participantX_prereq_match_idandparticipantX_prereq_match_result_source(from API via props) to display "W of Mx" or "L of Mx". - Editing Cue: Displays an SVG edit icon on matches; clicking the match group triggers
onMatchClickhandled bypage.tsxto open theMatchScoreEditor(styled as a popover).
- Calculates and displays a sortable standings table (W, L, D, Pts).
- Lists matches grouped by round.
- Inline Score Editing: When a match is clicked (and
onMatchClickis triggered, setting state inpage.tsx), it displays input fields directly within the match card for score entry. - Styled for dark theme readability.
EliminationStatsTable.tsx: Displays participant stats (MP, W, L, Points) for SE/DE formats.RoundRobinTable.tsx: Includes an integrated standings table.
GET /tournaments: List all tournaments.POST /tournaments: Create a new tournament.GET /tournaments/{id}: Get details for a specific tournament.PUT /tournaments/{id}: Update tournament details (e.g., status).GET /tournaments/{id}/participants: List participants for a tournament.POST /tournaments/{id}/participants: Add a participant.GET /tournaments/{id}/matches: Get all matches for a tournament.POST /tournaments/{id}/bracket: Generate the bracket/matches.PUT /tournaments/{id}/matches/{matchId}: Update a match (scores, status, etc.).
- Full Double Elimination Layout Perfection: Ensure
DarkChallongeBracket.tsxhandles all DE scenarios and edge cases for match placement and connector lines with high fidelity. Debug any visual issues with LB/GF. - True Inline SVG Editing (Advanced): If the popover-style editor for SE/DE isn't ideal, explore
<foreignObject>or pure SVG text input simulation (complex). - Robust Swiss System Implementation: Fully implement Swiss pairing logic in the backend and a corresponding frontend display.
- User Roles & Permissions: More granular control over who can create tournaments, add participants, report scores.
- Real-time Updates: Use WebSockets or similar for instant updates across all connected clients when scores change or brackets are updated.
- Seeding Management: UI for manual seeding or adjusting automated seeding.
- Tie-breaker Rules: Implement more complex tie-breaker rules for Round Robin standings (e.g., head-to-head results, score difference within matches).
- Responsive Design Improvements: Further fine-tune layouts for smaller screens.
- Testing: Comprehensive unit and integration tests for both backend and frontend.
- Error Handling & User Feedback: More detailed and user-friendly error messages. Loading indicators for all async actions.
- Accessibility (a11y): Ensure the bracket and tables are keyboard navigable and screen-reader friendly.
MIT