Add analytics integration with Horchposten backend #1

Merged
tas merged 2 commits from feature/analytics-integration into main 2026-03-08 19:42:59 +00:00
Collaborator

Summary

  • Adds src/game/stats.{c,h} — per-session gameplay metrics accumulator (kills, deaths, shots, dashes, jumps, pickups, damage dealt/taken, time elapsed, composite score)
  • Adds src/game/analytics.{c,h} — EM_JS bridge that calls Horchposten's session start/end endpoints via fetch(), with sendBeacon fallback on tab close
  • Instruments level.c (enemy kills, damage, shot hits, pickups, deaths) and player.c (jumps, dashes, shots fired)
  • Wires session lifecycle into main.c — sessions start on game begin, end on victory ("completed"), quit, restart, or tab close
  • Client UUID generated via crypto.randomUUID() and persisted in localStorage
  • Analytics URL and API key configurable via data-analytics-url / data-analytics-key attributes on the canvas container element
  • Non-WASM builds compile cleanly with no-op stubs
  • Zero new compiler warnings

Configuration

Set the analytics endpoint on the HTML container:

<div id="canvas-container"
     data-analytics-url="https://horchposten.example.com"
     data-analytics-key="your-api-key">

Test plan

  • Native build compiles cleanly (make)
  • WASM build compiles cleanly (make web)
  • With analytics URL configured: verify session start POST on game load
  • Complete a level → verify levels_completed increments
  • Die and respawn → verify death counter increments
  • Quit via pause menu → verify session end with reason "quit"
  • Complete all levels (victory) → verify session end with reason "completed"
  • Close tab → verify sendBeacon fires session end
  • Without analytics URL: verify no errors, game plays normally
  • Check Horchposten /admin/ dashboard shows recorded sessions

🤖 Generated with Claude Code

## Summary - Adds `src/game/stats.{c,h}` — per-session gameplay metrics accumulator (kills, deaths, shots, dashes, jumps, pickups, damage dealt/taken, time elapsed, composite score) - Adds `src/game/analytics.{c,h}` — EM_JS bridge that calls Horchposten's session start/end endpoints via `fetch()`, with `sendBeacon` fallback on tab close - Instruments `level.c` (enemy kills, damage, shot hits, pickups, deaths) and `player.c` (jumps, dashes, shots fired) - Wires session lifecycle into `main.c` — sessions start on game begin, end on victory ("completed"), quit, restart, or tab close - Client UUID generated via `crypto.randomUUID()` and persisted in `localStorage` - Analytics URL and API key configurable via `data-analytics-url` / `data-analytics-key` attributes on the canvas container element - Non-WASM builds compile cleanly with no-op stubs - Zero new compiler warnings ## Configuration Set the analytics endpoint on the HTML container: ```html <div id="canvas-container" data-analytics-url="https://horchposten.example.com" data-analytics-key="your-api-key"> ``` ## Test plan - [ ] Native build compiles cleanly (`make`) - [ ] WASM build compiles cleanly (`make web`) - [ ] With analytics URL configured: verify session start POST on game load - [ ] Complete a level → verify `levels_completed` increments - [ ] Die and respawn → verify death counter increments - [ ] Quit via pause menu → verify session end with reason "quit" - [ ] Complete all levels (victory) → verify session end with reason "completed" - [ ] Close tab → verify `sendBeacon` fires session end - [ ] Without analytics URL: verify no errors, game plays normally - [ ] Check Horchposten `/admin/` dashboard shows recorded sessions 🤖 Generated with [Claude Code](https://claude.com/claude-code)
LeSerjant added 1 commit 2026-03-08 19:15:40 +00:00
Implements session-based analytics tracking that sends gameplay
stats to the Horchposten API. Adds stats.{c,h} for accumulating
per-session metrics (kills, deaths, shots, dashes, jumps, pickups,
damage, time) and analytics.{c,h} with EM_JS bridge for fetch()
calls to the backend. Client ID is persisted in localStorage.
Session start/end hooks are wired into all game lifecycle events
(level transitions, restart, quit, tab close via sendBeacon).
Analytics URL/key are configured via data attributes on the canvas
container. Non-WASM builds compile with no-op stubs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LeSerjant added 1 commit 2026-03-08 19:32:34 +00:00
1. Race condition: session_end now waits for an in-flight
   session_start promise before sending, so quick restarts
   don't drop the end call.

2. beforeunload: replaced sendBeacon (which can't set headers)
   with fetch(..., keepalive: true) so the X-API-Key header
   is included and the backend doesn't 401.

3. Stats double-counting: removed stats_record_damage_dealt
   and stats_record_kill from damage_entity (which was called
   for all damage including player deaths). Now only recorded
   at player-sourced call sites (projectile hits, stomps).

4. Removed const-cast: analytics_session_end now takes
   GameStats* (non-const) since stats_update_score mutates it.

5. beforeunload now uses stashed stats from the last C-side
   session_end call instead of hardcoded zeroes. Session ID is
   cleared synchronously before async fetch to prevent races.

6. Removed unused stdint.h include from stats.h.
tas merged commit 702dbd4f9a into main 2026-03-08 19:42:59 +00:00
tas deleted branch feature/analytics-integration 2026-03-08 19:42:59 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: tas/major_tom#1