# Event Statistics: Page and Export Contract

Use this reference for routes, controller dispatch, views, 404 behavior, cache, CSV, or translations.

## Route State Machine

Only `event-statistics` is registered. Query state is hierarchical:

```mermaid
flowchart TD
    R[event-statistics] --> E[All events]
    R1[event_id] --> V{Completed event?}
    V -->|no| N[404]
    V -->|yes| G[Guild list]
    R2[event_id + guild_id] --> VG{Guild belongs to event?}
    VG -->|no| N
    VG -->|yes| P[Guild player list]
    R3[event_id + guild_id + player_id] --> VP{Player belongs to event and guild?}
    VP -->|no| N
    VP -->|yes| D[Player detail]
    DL[event_id + guild_id + download=guild] --> VG
    VG -->|valid download| C[Permanent guild CSV]
```

Strict rules:

- `event_id` and `player_id`: positive integers.
- `guild_id`: non-negative integer; zero is valid.
- A child parameter without all parents returns 404.
- Any drill-down/export requires `status='completed'` at model lookup time.
- `download=guild` is the only accepted export action.
- Unknown IDs, parent mismatches, and other download values return the standard page 404.

## Screen Contract

| State | Columns/content | Cache |
| --- | --- | --- |
| Event list | Event, server-local Date, Status | None |
| Guild list | Guild, Players | HTML, 900 seconds |
| Player list | Name, `HH:MM:SS`, Kills, Deaths, Times Revived, Revives Given | HTML, 900 seconds |
| Player detail | Event/player/guild identity, totals, all raw statistics | None |
| Guild CSV | Guild player rows | Permanent |

Completed event/guild/player names are links only within the historical hierarchy. Do not use normal profile/guild URLs because those resolve live data.

Use `table ranking-table` for lists. Use the profile page's `row fake-table` plus `ComponentsTemplate::printFields()` for details. Do not copy profile avatar, class, spouse, account, or online-state behavior.

## Cache Keys

Require `src/core/modules/Cache/Cache.php` and use category `event-statistics`.

```text
Guild HTML:  type=html, name=guilds_{eventId}_{LANGUAGE}, maxTime=900
Player HTML: type=html, name=players_{eventId}_{guildId}_{LANGUAGE}, maxTime=900
Guild CSV:   type=csv,  name=event_{eventId}_guild_{guildId}, maxTime=null
```

HTML keys include language because headings, statuses, alerts, and `No Guild` are translated. CSV is language-independent and therefore has one permanent file per event/guild.

Use `Cache::read()` when content must be assigned to the shell; `Cache::load()` emits/includes immediately and is unsuitable before the theme header. Generate missing HTML with output buffering and persist using `Cache::buildFromString()`.

## CSV Contract

There is no event-wide or single-player export.

Encoding/dialect:

- UTF-8 BOM (`EF BB BF`).
- Comma delimiter.
- Double-quote enclosure as needed.
- CRLF record endings.
- English snake_case headers for stable permanent files.
- Formula-injection protection for text cells.

Exact column order:

```text
event_id
player_id
player_name
guild_id
guild_name
event_map_seconds
event_time_hms
kills
deaths
times_revived
revives_given
kills_same_guild
kills_enemy_guild
kills_allied_guild
kills_neutral
deaths_same_guild
deaths_enemy_guild
deaths_allied_guild
deaths_neutral
deaths_non_player
manual_revives
water_revives_given
water_revives_received
```

Exclude player-row `id`, `created_at`, and `updated_at`. `event_time_hms` is derived from `event_map_seconds`; all other raw values preserve snapshot values.

Suggested attachment filename:

```text
event-{eventId}-guild-{guildId}.csv
```

## Translation Keys

Add exact English source keys to Spanish and Portuguese dictionaries as used by `__()`:

```text
Event Statistics
Event
Date
Status
In Progress
Completed
Guild
Guild ID
Players
Player ID
Time
Kills
Deaths
Times Revived
Revives Given
No Guild
Download CSV
Event Information
Player Information
No events found.
No guilds found.
No players found.
```

Also translate labels for each raw kill/death/revive field shown in player detail. Reuse existing translation keys where the exact key already exists.
