Skip to content

feat(contests): complete Contests bug fix drive - #57

Open
RsbhThakur wants to merge 31 commits into
devfrom
feat/contests-bugfix-drive
Open

RsbhThakur wants to merge 31 commits into
devfrom
feat/contests-bugfix-drive

Conversation

@RsbhThakur

@RsbhThakur RsbhThakur commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Resolves #33
Resolves #41
Resolves #42
Resolves #43
Resolves #44

Summary

This pull request unifies and lands the complete Contests Bug Fix Drive (Epic #33), integrating four interconnected sub-issues (#41, #42, #43, #44) that overhaul tournament brackets, submission integrity, problem statement rendering, spectator access, team management, and match activity feeds.

All commits and author attributions from the respective pull requests (PR #49, PR #52, PR #55, and PR #56) have been preserved in the git history to maintain full contributor credit.


🎯 Issue #33 Checklist Coverage

  • Creation bugs: Dynamic >= 1m buffer for casual 1v1 and >= (deadline + 1)m for tournaments; synced quick-add buttons and hint copy.
  • Wrong problem link: Fixed Codeforces URL formatting for problem IDs with trailing alphanumeric divisions (e.g., 1678B1 -> https://codeforces.com/contest/1678/problem/B1).
  • Status indicator on left bar: Realtime online/offline indicators for all team and competitor members.
  • Warning to exit, don't show back button: Added modal warning guard when attempting to navigate away from an active match.
  • Countdown timer for setup/forfeiture: Persistent disconnect countdown timers using delayed BullMQ jobs that survive browser refresh.
  • Unified activity feed: Realtime room.activity events for solves, critical reclaims, advances, and match endings, with backfilled history on reconnect.
  • Match history & DB persistence: Displays final tournament match placement instead of Round 1; corrected forfeit/tie scoring (+1/-1); safe Redis cache cleanup when all rooms end.
  • Spectator mode: Configurable access restrictions ("none", "all", "admin_creator", "club_members"), server-side canSpectate authorization, and disabled competitor interactions for viewers.
  • Time/score per question & overall: Support for points and timeLimitMinutes per problem slot, overall match duration, and Redis worker synchronization.
  • Submission integrity: Enforces verified Codeforces handle, room/team membership check, unrevealed problem checks, and rejects post-completion submissions.
  • Security & authorization: Enforces server-side isHead() check on tournament and open contest creation, normalizing unprivileged requests to casual 1v1.
  • Problem statement according to spec: Persists and displays full HTML statement, input/output specifications, constraints, notes, and sample test cases.
  • Team assignment interface: Private team join codes, team invites, join requests, and automatic leadership reassignment on leader departure (preventing ghost teams).
  • Code Runner integration: Local in-browser C++ and Python execution against problem sample cases.
  • Bracket tournament engine: Upper, Lower, and Grand Final progression for double elimination with deterministic Byes and React Flow visualization.

Detailed Sub-Issue Breakdown

1. Tournament Bracket Progression, Creation Fixes & Security (Resolves #43 — PR #49 by @RsbhThakur)

  • Security & Authorization: Enforces server-side isHead authorization for tournament and open contest creation, normalizing unprivileged attempts to casual 1v1 matches.
  • Timing & Buffer Synchronization: Solves the start-time desynchronization bug by validating a dynamic >= 1 minute buffer for casual 1v1 and >= (registrationDeadlineMinutes + 1) minutes for scheduled tournaments, updating quick-add buttons and modal hints dynamically.
  • Per-Question Scoring & Duration: Adds granular points and time limit fields (timeLimitMinutes) to problem slots and presets. Worker pipelines stamp currentProblemStartTime in Redis on Blitz problem advances and preserve fine-tuned problem points.
  • Double Elimination Bracket Engine: Implements Upper, Lower, and Grand Final bracket generation and progression with deterministic Byes, atomic room promotions (findOneAndUpdate), and non-blocking Redis key cleanup.
  • Interactive Dual-Bracket Visualizer: Adds segmented view filters (All, Upper, Lower, Grand Final) and a dual-tree React Flow layout.

2. Problem Engine, Submission Integrity & Code Runner (Resolves #41 — PR #52 by @Priyangshu-Mandal)

  • Problem Statement & Sample Cases: Loads and displays full problem statements, input/output specifications, constraints, and sample test cases inside contest rooms.
  • Local Code Runner Integration: Integrates local C++ and Python code execution directly in contest rooms with sample case testing.
  • Submission Integrity: Rejects submissions if Codeforces handle is missing, verifies team and room membership, ensures problems are revealed, and rejects submissions after match completion.
  • Submission Persistence: Atomically upserts accepted submissions in ContestSubmission for persistence and match result integrity.
  • URL Generation: Fixes Codeforces problem URL generation for complex identifiers like 1678B1.

3. Spectator Mode, Team Management UX & Match History (Resolves #44 — PR #55 by @DefineAditya)

  • Spectator Mode: Adds spectatorRestriction to ContestMatch ("none", "all", "admin_creator", "club_members") with server-side canSpectate access control, disabling competitor actions for spectators.
  • Team Management UX: Implements private team join codes, team invitations, join requests (ContestTeamRequest, ContestRegistrationTeam), and automatic leadership reassignment on leader departure (preventing ghost teams).
  • Match History & Persistence: Sorts tournament matches by latest actualStartTime to display final placement rather than Round 1, fixes forfeit/tie scoring (1 pt for winner, -1 for forfeiter), and protects Redis room cache until all rooms finish.

4. Persistent Forfeit Timers & Realtime Activity Feeds (Resolves #42 — PR #56 by @ronits2407)

  • Persistent Forfeit Timers: Implements persistent disconnect timers via delayed BullMQ jobs that survive browser reloads, rendering live countdown badges for disconnected competitors.
  • Realtime Activity Feeds: Unified room.activity event logging across solves, critical reclaims, problem advances, and match endings, with backfilled activity history on reconnection.
  • Status Indicators & Navigation Guards: Visual presence indicators on the sidebar and navigation exit warnings during active matches.

Technical & Architectural Integrity

  • Fail-Closed Authorization: All privileged contest endpoints independently verify user access levels via server-side session checks.
  • Concurrency & Idempotency: Redis keys for problem locks, room state sync, and team presence use atomic primitives and BullMQ delayed job tracking (jobId: disconnect-timeout-${roomId}-${userId}).
  • Zero Schema Breaking Changes: New schema fields are optional with sensible defaults; fully backward-compatible with existing contests in MongoDB.

Verification & Testing

  • TypeScript Compilation: pnpm typecheck (tsc --noEmit) passes with 0 errors.
  • ESLint: pnpm lint (eslint .) passes with 0 warnings/errors.
  • Test Suites (Vitest):
    • tests/integration/contests-spectator.test.ts (6/6 passed)
    • tests/integration/contest-presets.test.ts (7/7 passed)
    • src/lib/api/schemas/contestAction.test.ts (6/6 passed)
    • src/types/bracket.test.ts (14/14 passed)
    • src/lib/contests/problemContent.test.ts (3/3 passed)
    • src/components/contests/roomPresentation.test.ts (2/2 passed)
    • tests/integration/blog-revisions-history.test.ts (27/27 passed)
  • Local Services: Verified against MongoDB replica set (rs0) and Redis containers.

Contributor Credits

Sub-Issue Pull Request Contributor
#43 (Tournament Bracket Progression, Creation Fixes & Security) PR #49 @RsbhThakur
#41 (Problem Engine, Submission Integrity & Code Runner) PR #52 @Priyangshu-Mandal
#44 (Spectator Mode, Team Creation Interface & Match History) PR #55 @DefineAditya
#42 (Persistent Forfeit Timers & Realtime Activity Feeds) PR #56 @ronits2407

@RsbhThakur RsbhThakur changed the title Feat/contests bugfix drive feat(contests): complete Contests bug fix drive (#33) Sep 7, 2026
@RsbhThakur
RsbhThakur marked this pull request as ready for review September 7, 2026 07:47
@RsbhThakur RsbhThakur changed the title feat(contests): complete Contests bug fix drive (#33) feat(contests): complete Contests bug fix drive Sep 7, 2026
… team display names

- Fix Redis activity log trimming to keep the latest 50 entries using lTrim(key, -50, -1) instead of truncating newest items
- Add defensive JSON parsing with filter in SSE stream reconnection to prevent stream termination on corrupted log strings
- Query User directly in cfSyncWorker for 1v1/solo display names with getDisplayName fallback and pizza badge formatting
- Remove raw console.error calls in createRoomContestAction and createBracketContestAction per CONTRIBUTING.md
- Fix React exhaustive-deps lint warning in ManageTeamModal
- Add comprehensive end-to-end integration test suite covering room creation, Codeforces URLs, double elimination brackets, spectator controls, team codes, and activity log queues
… logging

- Align CreateRoomModal client-side start time buffer check with casual 1v1 1-minute minimum buffer
- Log Accepted verdict and specific Codeforces not-found verdicts in room activity feed
- Add immediate error logging to activity feed when sync API call fails
- Include type: 'sync.failed' and problemId in early cfSyncWorker rejections so events pass stream schema validation
… time quick-adds

- Replace vertically stacked details dropdowns with tabbed ContestProblemWorkspace (Statement, Code Runner) in Blitz and Arena rooms
- Add plain prop support to ContestProblemContent and ContestCodeRunner for embedded layout
- Update start time quick-add minutes to [2, 3, 5, 10] for casual 1v1 and [deadlineMinutes + 2, ...] for tournaments to eliminate minute truncation false rejections
…and e2e test suite

- Add problem card selection to ArenaRoomClient so competitors can switch the active problem in ContestProblemWorkspace
- Replace hardcoded hex colors in ContestProblemContent.module.scss with CSS theme variables and add fallback notice with Codeforces link when statementHtml is missing
- Expand contests-bugfix-drive-e2e.test.ts to 19 tests verifying start time buffer checks, room presentation utilities, and bracket math end-to-end
@maydayv7

maydayv7 commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

what is up with the Code Runner and problem statement, I just expected yall to provide a button to open the already implemented Code Runner, which already carries the problem part

@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from ronits2407 Sep 7, 2026
@Coding-Club-IITG Coding-Club-IITG deleted a comment from maydayv7 Sep 7, 2026
@RsbhThakur

RsbhThakur commented Sep 7, 2026

Copy link
Copy Markdown
Contributor Author

what is up with the Code Runner and problem statement, I just expected yall to provide a button to open the already implemented Code Runner, which already carries the problem part

It was implemented by @Priyangshu-Mandal, so not much idea, but prompting up to an LLM it seems that the current implementation seems fine only. but tell if any changes are required:

1. Existing /internal/solve vs. Contest Architecture

We looked into linking directly to the existing /internal/solve page, but found that /internal/solve is currently coupled to the POTD flow:

  • SolvePage (src/app/(protected)/internal/solve/page.tsx) only hydrates content (statement HTML, limits, sample testcases) when a challengeId is present via getSolveChallenge(challengeId). If only platform, contestId, and problemIndex are passed, content remains null, hiding the statement tab and sample cases.
  • The sync mechanism on /internal/solve (syncMySubmission) is wired to POTD challenge streak/points rather than the contest room submission integrity & scoring pipeline (/api/contests/sync).

2. What PR #52 / #57 Did Instead

Rather than rebuilding the editor or runner from scratch, PR #52 (@Priyangshu-Mandal) reused the shared core components from @/components/shared/code-runner (CodeEditor, LanguageSelector, TestCasePanel) inside ContestProblemWorkspace:

  • It embeds the statement and a lightweight sample runner as clean tabs ([Statement] | [Code Runner]) directly inside the match room.
  • This keeps contestants anchored to the active match HUD (live countdown timers, opponent solve progress, match activity feed, and the contest CF sync button) without needing to juggle multiple browser tabs during rapid-fire matches like Blitz or 1v1.

Next Steps / Your Preference

The current inline tabbed layout is fully functional, verified, and reuses the shared code-runner primitives. However, if you'd prefer to keep the contest room HUD completely uncluttered:

  1. Keep the current inline tabbed workspace (Statement + Code Runner tabs in-room).
  2. Or replace the Code Runner tab with an "Open Code Runner" button/modal (or generalize /internal/solve to accept contest problem payloads in a new tab).

RsbhThakur and others added 8 commits September 8, 2026 00:43
- Sort activity feed entries by descending timestamp before rendering

- Make toast notifications fully opaque to prevent text bleeding

- Differentiate selected open problems from locked ones in the Arena grid

- Add scrolling wrappers to Arena center stage to keep page layout fixed
…n fine-tuned mode, and restrict bulk problems to valid ratings
- Rename "Bracket (Knockout)" to "Bracket" across the UI (presets, wizard, create room modal).
- Fix "Remove Preset" button overflow in PresetManager UI.
- Correct spectator mode logic to align UI selection properly with backend values.
- Refactor and organize internal tournament wizard components and routes.
- Prevent redundant "Match Preset" selection when creating a Bracket room from a parent preset.
- Fix backend validation error by defaulting un-preset brackets to "custom" presetId.
- Fix Zod validation crash for bulk tournaments by stripping empty strings from fineTunedProblems.
- Hide "Display Name" inputs when registering as a solo player in any format, seamlessly defaulting to CF handle.
- Rearrange Bracket Settings layout to position Elimination Type and Seeding options before problem selection.
- Revert mock AC verdict in cfSyncWorker to restore original codeforces sync behavior
- Add allback node prop to CompatibleImage for broken profile pictures (404 handling)
- Render initials in BracketRoomClient when user profile avatars fail to load
- Update getBracketSnapshot to prioritize 
oom.winnerTeamId when assigning match winners, accurately reflecting timeout/underdog rating tiebreakers on edges
- Fetch and pass all user team IDs (currentUserTeamIds) in page.tsx so that users are correctly identified as participants in advanced rounds (e.g. Grand Final) and allowed to join the waiting room
- Add �racketSettings to ContestListingItem dto
- Update ContestListingClient to display 'Double Elim Bracket' for double elimination formats
- Update MatchHistoryClient tag to display 'Double Elim' appropriately
- **Presets**: Apply preset name and description if form fields are empty. Add `flex-wrap` and `flex-end` alignment to slot rows in `PresetManager`.
- **Bracket**: Emit `contest.bracket_update` from `cfSyncWorker` and `reconciliationWorker` to ensure clients redraw bracket lines and node states on score updates and room completions.
- **Tests**: Use valid 24-char hex ObjectIDs in session mocks and supply required `creatorId` and `isGlobal` fields to fix `ContestPreset` validation errors. Update preset assertions for members. Fix import and call for `createBracketContest` in e2e tests.
@ronits2407
ronits2407 force-pushed the feat/contests-bugfix-drive branch from 1499da7 to 54e6802 Compare September 8, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment