跳到正文
DEV Community· SHREYANSH GIRI·· 4 小時前AI 評分42

CodeClash:1 對 1 Codeforces 對決加入本地 LLM Ghost Racer

CodeClash: 1v1 Codeforces Duels, Now Haunted by a Local-LLM Ghost Racer

AI 導讀

CodeClash 是讓玩家在相同 Codeforces 題目上競賽的即時 1 對 1 程式競賽平台,並加入本地運行的 Ghost Racer。這個以開放權重模型驅動的智能體會嘗試解題、執行樣例測試並根據失敗修訂,最後可能勝出或退場。

正文

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine

What I Built

CodeClash is a real-time 1v1 competitive programming arena. Two players are matched by Elo, handed the same authentic Codeforces problem, and race to land the first Accepted verdict. It has ranked matchmaking, private 6-character challenge rooms, an embedded multi-language IDE, live verdict tracking, and a global leaderboard.

For Ghost in the Machine, I took the theme literally from racing games. In a racing game, a ghost is a translucent replay of a past run that you race against: a dead lap that still drives. CodeClash's Ghost Racer is that idea for competitive programming: an open-weight-model agent, running locally, that races you on the same problem, attempting solutions, failing sample tests, retrying, and either beating you or fading out. No second human required, and no queue wait at 3 a.m.

Demo

Live app: https://code-clash-kohl.vercel.app

Backend API: https://codeclash-hmgz.onrender.com

Code

GitHub logo ShreyanshGiri08 / CodeClash

CodeClash is a real-time 1v1 competitive programming platform built for speed and precision. Race head-to-head against rival coders or challenge friends on curated Codeforces problems, track live submission verdicts, and climb the global Elo leaderboard in real-time.

⚡ CodeClash — Real-Time 1v1 Competitive Programming Esports Platform

Live App Backend API

🚀 Live App Deployment: https://code-clash-kohl.vercel.app
⚡ Backend API Server: https://codeclash-hmgz.onrender.com

CodeClash is a state-of-the-art, real-time competitive programming esports platform designed for high-speed duels on authentic Codeforces problems. Featuring Elo-rated matchmaking, 6-character private challenge rooms, Valorant-style match entrances, an embedded multi-language IDE with local execution, a smart non-destructive algorithm snippet vault, dynamic analytics radar charts, 3D holographic badges, zero-asset Web Audio synthesis, and an advanced client-side TeX math statement parser.


📑 Table of Contents

  1. Technical Stack
  2. System Design & Architecture Flowcharts
  3. Algorithmic & Mathematical Models
  4. Exhaustive Feature Directory
  5. Statement Slicer & TeX Math Cleaning Engine
  6. Performance Optimizations & Resilience
  7. Project Directory Structure
  8. Installation & Local Setup
  9. Environment Variables

🛠 Technical Stack

Frontend Subsystems

  • Core Framework: React 18, Vite 5, React Router v6
  • Styling & Micro-Interactions: Tailwind CSS v4, Vanilla CSS Custom Variables, Framer Motion (3D spring physics, layout…

How I Built It

The arena (the nuts and bolts)

Stack: React 18 + Vite + Tailwind v4 + Framer Motion on the frontend; FastAPI on Uvicorn, asyncpg, and Neon serverless PostgreSQL on the backend. Frontend on Vercel, API on Render.

Matchmaking without Redis. Ranked queue is an in-memory structure behind an asyncio.Lock with an expanding band search: ±100 Elo at 0–10s, widening in steps to ±500 by the 120s timeout. Both sides are checked, so a new player's band is tested against the queued player's expanded band. For a single-process free-tier deploy this gives zero-latency lookups with no extra infra. (Multi-worker would move to Redis sorted sets with ZRANGEBYSCORE and Redlock; I documented that trade-off rather than pretending the problem doesn't exist.)

Verdicts come from Codeforces itself. There is no custom judge to cheat. The server polls the official user.status endpoint and decides the winner from real submissions. Two details that mattered:

  • A 60-second clock-drift buffer (effective_start = after_timestamp - 60) so server clock offsets don't cause a legit AC to be missed.
  • Tie-break by creationTimeSeconds when both players solve it, so the earliest Accepted wins.

Idempotent finalization. Race results can be triggered at the same moment by player 1, player 2, or background polling. A check-before-write plus an atomic SQL guard (UPDATE races SET status='finished', elo_applied=TRUE ... WHERE id=$1 AND elo_applied=FALSE) means Elo is applied exactly once. Without it you get +24 instead of +12. Elo is standard zero-sum with K = 32 (with a provisional K period for new accounts).

Scraping that survives Codeforces. Codeforces has no statement API, so statements are scraped (httpx + BeautifulSoup) and cached with a TTL. When direct access fails there's a fallback cluster: Jina Reader → AllOrigins → CodeTabs. On the client, a custom statement slicer strips nav bars, flags and footers, and a TeX cleaner turns \ldots, \leq, 10^{9}, a_1, \dots, a_n into ..., ≤, 10⁹, a₁, ..., aₙ.

Code Studio. Embedded editor for C++17, Python 3.10, Java 17 and JavaScript. Non-JS languages run through the Piston API; JS runs in a client-side sandbox. Output is diffed against expected sample output. A snippet vault (Fast I/O, DSU, ModPow, Segment Tree) inserts non-destructively: Fast I/O goes inside main(), helper structs go above it.

Small things that make it feel alive. A Web Audio synthesizer with zero audio assets (oscillators and gain nodes for every UI sound), a Valorant-style 3.5s match entrance, 3D holographic badges, a Ctrl+K command palette, and a 6-axis skill radar computed as min(100, max(25, Elo/25 + 7·CF_solved_T + 12·clash_wins_T)).

Boring-but-real engineering: pool recycling for Neon (max_inactive_connection_lifetime=180), sliding-window rate limits (5 queue requests/min, 15 verdict checks/min), and a /health endpoint that actually pings the DB.

The Ghost (the open-source AI part)

The Ghost is an agent, not a single prompt. It runs on an open-weight model served locally, and the model is a config value, so swapping it is a one-line change.

  • Agent loop: Read statement → plan approach → write solution → run it against the sample tests in a sandbox → read the failure → revise. The loop is bounded to a fixed number of attempts, so it can lose, and losing convincingly is the point.
  • Tools it can call: read_problem, run_code(lang, source, stdin) and submit_attempt.
  • Pacing: The Ghost's visible progress is paced to a target Elo, so a 1200-rated Ghost doesn't solve a 2000 problem in 8 seconds.
  • Integration: The Ghost joins the existing race room as a participant, emitting the same RACE_UPDATE events a human opponent would, so the arena needed almost no changes.

Why Does Open Innovation Matter?

  • Cost. Racing the Ghost costs nothing per match. A closed API charges per token on every attempt of every retry loop, and an agent that iterates several times per problem would burn through a free tier fast.
  • Swappable brains. Because the model is a config value, I can drop in a bigger or smaller open-weight model and feel the difficulty change. That is the difficulty slider, and it's impossible when the model behind an API can change or be deprecated underneath you.
  • No lock-in. A ghost that depends on a hosted service dies when the service does. Fitting for the theme, a ghost built on open weights can't be switched off by someone else.
  • Control of the agent loop. With open tooling I decide the sandbox, the attempt cap, the retry policy and the pacing. Those are product decisions here, not API parameters.

來源:DEV Community · dev.to