Skip to content

Latest commit

 

History

History
259 lines (195 loc) · 8.01 KB

File metadata and controls

259 lines (195 loc) · 8.01 KB

CS2 Web Server

A Ruby Sinatra web application that serves as the frontend/UI layer for the cs2-reviewer project. It provides a web interface to upload CS2 demo files, view parsed match data, and visualize kill positions on interactive map overlays.

Project Structure

web_server/
├── main.rb                    # Sinatra application (routes & logic)
├── Gemfile                    # Ruby dependencies
├── .ruby-version              # Ruby 3.3.4
├── lib/
│   └── mod.rb                 # Empty module (placeholder)
├── views/                     # Haml templates
│   ├── layout.haml           # HTML layout wrapper
│   ├── index.haml            # Upload form
│   └── upload.haml           # Results display with map
├── public/                    # Static assets
│   ├── css/                  # Bootstrap 5
│   ├── js/                   # Bootstrap + canvas-renderer.js
│   ├── maps/                 # 9 CS2 map radar images
│   └── app/                  # Alternative Vite+Svelte+TS frontend
├── spec/                      # RSpec tests (minimal)
└── tmp/
    └── boltobserv/           # Reference project (open-source CS2 radar)

Installation

# Install Ruby dependencies
bundle install

# Ensure the demo_parser binary is built
cd ../demo_parser
go build -o out/bin/cs2-reviewer ./cmd/cs2-reviewer
cd ../web_server

Usage

# Development mode (auto-reload on file changes)
bundle exec rerun -- rackup

# Production mode
bundle exec puma

# Access the application
# Open http://localhost:9292 in your browser

Core Application Flow

Routes

GET '/' - Landing page with file upload form

POST '/upload' - Main workflow:

  1. Receives uploaded demo file via multipart form data
  2. Calls Go parser binary: ../demo_parser/out/bin/cs2-reviewer
  3. Captures JSON output from stdout
  4. Parses data with Oj (fast JSON library)
  5. Maps to Ruby Structs (DemoInfo, Team, Player, Round)
  6. Renders results with interactive map visualization

GET '/test' - Development endpoint (reads cached demo JSON)

GET '/app' - Serves alternative Vite+Svelte+TypeScript SPA

Data Flow

User Upload → Sinatra → Go Parser → JSON → Ruby Structs → Haml → HTML → JS Interactivity

Features

1. Demo Upload & Parsing

  • Browser-based interface (no command-line required)
  • Upload .dem files directly
  • Automatic parsing via Go backend

2. Match Data Display

  • Demo metadata (map name, server, duration in seconds/ticks/frames)
  • Team information with player rosters
  • Round-by-round breakdown:
    • Round number, start/end times
    • Winner and loser team IDs
    • Winning reason code
    • Complete kill feed

3. Interactive Map Visualization

  • Click on any kill event to visualize player positions
  • Colored dots on map overlay:
    • Red = Victim position
    • Blue = Attacker position
    • Green = Assister position (if exists)
  • Supports split-level maps (Nuke, Vertigo with upper/lower floors)

4. Supported Maps

Includes radar images and coordinate metadata for:

  • de_ancient
  • de_anubis
  • de_dust2
  • de_inferno
  • de_mirage
  • de_nuke (split-level)
  • de_overpass
  • de_train
  • de_vertigo (split-level)

Technical Details

Interactive Map System

Coordinate Transformation: CS2 uses 3D world coordinates (X, Y, Z in game units). These are converted to 2D SVG coordinates using:

posX = (offsetX + x) / ratio
posY = (offsetY - y) / ratio  // Note Y-axis inversion

Each map has specific transformation parameters stored in public/js/canvas-renderer.js.

Split-Level Maps: Nuke and Vertigo have upper/lower levels. The Z-coordinate determines which transformation to use:

  • Nuke: Z < -480 = lower level
  • Vertigo: Z < 11680 = lower level

Dependencies

Web Framework:

  • sinatra - Lightweight web framework
  • sinatra-contrib - Sinatra extensions
  • rackup - Rack server interface
  • puma - Production-grade multi-threaded web server

Templating & Parsing:

  • haml - HTML abstraction markup language
  • oj - "Optimized JSON" - fastest Ruby JSON parser

Development:

  • rerun - Auto-restart server on file changes
  • zeitwerk - Modern code autoloader

Testing:

  • rspec - BDD testing framework

Ruby version: 3.3.4

Architecture

Stack

  • Backend: Ruby 3.3.4 + Sinatra + Puma
  • Parser: Go binary (separate component in ../demo_parser)
  • Frontend: Bootstrap 5 + Haml templates
  • Interactivity: Vanilla JavaScript with SVG manipulation
  • Assets: CS2 map radar images (sourced from Boltobserv project)

Data Modeling

The application uses Ruby Structs for lightweight data modeling:

DemoInfo = Struct.new(:mapName, :serverName, :durationInSec, :durationInTick, :durationInFrame)
Team = Struct.new(:id, :name, :players)
Player = Struct.new(:steamID, :gameID, :name)
Round = Struct.new(:roundNumber, :startTime, :endTime, :winningReason, :winnerId, :loserId, :killFeed)

Note: These Structs simplify the full Go output, omitting financial data and detailed team states for display purposes.

Alternative Frontend

An experimental Vite + Svelte + TypeScript SPA is in development under public/app/. This represents a more modern, reactive UI approach alongside the traditional server-rendered templates.

Access it via: http://localhost:9292/app

Status: Incomplete/experimental

Boltobserv Integration

The tmp/boltobserv/ directory contains a reference copy of Boltobserv, an open-source CS2 observer radar tool (GPL-3 licensed).

Purpose:

  • Source of high-quality map radar images
  • Reference for coordinate transformation systems
  • Inspiration for advanced visualization features

The map assets in public/maps/ and coordinate metadata in canvas-renderer.js are derived from this project.

Known Issues

Bugs:

  • /test route has syntax error on line 60 (missing =)

Missing Features:

  • No error handling (Go binary failures, corrupt demos, wrong file types)
  • No file validation (any file can be uploaded)
  • No loading indicators (parsing large demos blocks synchronously)
  • No persistence (demos not stored, no history)
  • No way to clear map circles (persist until page refresh)
  • No zoom/pan functionality on maps

Incomplete:

  • lib/mod.rb is an empty placeholder
  • Svelte SPA incomplete
  • Minimal test coverage
  • Generic boilerplate in original README

Data Loss:

  • Ruby Structs drop financial stats and detailed team states from Go output
  • Only basic round/kill data is displayed

Limitations:

  • Hardcoded map metadata (code changes required for updates)
  • Only 8 maps have transformation metadata (de_train missing)
  • No coordinate bounds validation
  • Hardcoded relative path to Go binary

Use Cases

This web interface enables:

  1. Browser-based demo analysis - No command-line required
  2. Match review - View teams, rosters, round outcomes
  3. Kill position analysis - Visual representation on actual maps
  4. Spatial analysis - Understand engagement locations
  5. Post-match breakdown - Review timing, round flow, statistics

Perfect for CS2 players and teams wanting accessible demo review tools.

Development

Running Tests

bundle exec rspec

Project Status

  • ✅ Core functionality works (upload → parse → display → visualize)
  • ⚠️ Missing production polish and error handling
  • 🚧 Exploring multiple frontend approaches (Haml + Svelte)
  • 🚧 Mid-development based on git history

Integration with demo_parser

The web server calls the Go demo parser as a subprocess:

stdout, _stderr, _status = Open3.capture3('../demo_parser/out/bin/cs2-reviewer', tempfile.path)

Requirements:

  • Go binary must be built and present at ../demo_parser/out/bin/cs2-reviewer
  • Binary must output valid JSON to stdout
  • Synchronous execution (blocks until parsing completes)

License

This project uses assets and coordinate systems derived from Boltobserv, which is licensed under GPL-3.