Files
fragalytics/README.md
T
2026-04-20 18:15:08 +00:00

5.1 KiB

Fragalytics MVP

Fragalytics is a self-hosted MVP for Counter-Strike 2 demo analysis and highlight generation built in C# on ASP.NET Core. You upload .dem files manually, the app stores them, parses them in a background worker, scores highlight moments with explainable rules, persists the results in a local JSON-backed store, and creates clip job records for future rendering.

Why this C# stack

  • Web app: ASP.NET Core Razor Pages. It keeps the UI simple, local, and maintainable without adding a separate frontend build.
  • Background work: BackgroundService. Good enough for a single-node MVP and easy to replace later with a queue worker.
  • Persistence: file-backed JSON store. It avoids external package dependencies in this environment while still giving durable local storage and a clean repository boundary.
  • Parsing: parser adapter abstraction. The app can run today with the sample adapter and can be pointed at an external parser process later.
  • Scoring: explicit service layer with versioned rules and explainable output.

What is implemented

  • Manual .dem upload
  • Background demo parsing
  • Persistent storage
  • Models for demos, matches, rounds, players, events, highlights, scoring profiles, and clip jobs
  • Explainable highlight scoring
  • Highlight tags: multikill, headshot, opening_kill, clutch, 1vX, wallbang, smoke_kill, round_win
  • Clip job records with start_tick, end_tick, status, renderer, and payload
  • Web UI for demos, match details, highlights, and clip jobs
  • Rescoring when scoring rules change
  • Parser adapter abstraction
  • Future render-worker abstraction
  • Docker setup
  • Tests for scoring and basic ingest flow

Run locally

DOTNET_CLI_HOME=/tmp/dotnet-home DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 dotnet run --project src/Fragalytics.Web

Open http://localhost:5000 or the URL printed by ASP.NET Core.

Run the render worker

The render worker is a separate process:

DOTNET_CLI_HOME=/tmp/dotnet-home DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 dotnet run --project src/Fragalytics.RenderWorker

Right now it uses the sample-copy backend. That backend does not render from a .dem; it claims pending clip jobs and attaches a configured sample .mp4 or .webm file so the end-to-end worker flow is in place.

Docker

docker compose up --build

Open http://localhost:8080.

Configuration

Main settings live in appsettings.json.

  • Fragalytics:DataDirectory: persistent app state root
  • Fragalytics:UploadDirectory: uploaded demo path
  • Fragalytics:WorkerPollSeconds: polling interval for the hosted worker
  • Fragalytics:Parser:Mode: sample or external
  • Fragalytics:Parser:ExternalCommand: executable for a real parser sidecar
  • Fragalytics:Parser:ExternalArguments: argument template, with {demoPath} placeholder
  • Fragalytics:RenderWorker:Backend: render backend name, currently sample-copy
  • Fragalytics:RenderWorker:SampleClipPath: source media file used by the stub backend
  • Fragalytics:RenderWorker:TempDirectory: worker scratch directory
  • Fragalytics:RenderWorker:PollSeconds: clip-job polling interval

Scoring

Scoring rules live in scoring-rules.json. Change the weights or threshold, then use Rescore All Matches from the home page. The app stores a hashed scoring version on each highlight so rule changes are traceable.

Rendering Roadmap

The app can now play uploaded clip files, but it still does not render video directly from CS2 demos. The step-by-step implementation plan for real demo-to-video rendering is documented in docs/rendering-from-cs2-demo.md.

Assumptions

  • This MVP is kill-centric. It does not yet score utility-only, positioning-only, or movement-only moments.
  • The default parser is the deterministic sample adapter so the app is runnable offline and testable in this environment.
  • Real CS2 parsing is expected to come from an external parser process wired through IDemoParserAdapter. That keeps the ASP.NET Core app stable even if the parsing implementation changes.
  • The persistent store is intentionally simple for a local MVP. If this moves beyond single-node use, replace the store with SQLite or Postgres behind the same service boundary.
  • Rendering is intentionally not implemented. Clip jobs are created as durable work intents for a future render worker. Current status: the separate render-worker scaffold exists, but the only backend today is a stub that copies a known video file instead of driving CS2.

Tests

DOTNET_CLI_HOME=/tmp/dotnet-home DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 dotnet run --project tests/Fragalytics.Web.Tests

Extension path

  • Replace the JSON store with SQLite or Postgres
  • Move background processing into a separate worker process
  • Add a real parser sidecar that emits the normalized ParsedDemo JSON contract
  • Replace the sample-copy render backend with real CS2-driven capture
  • Add richer event ingestion and rule editing in the UI