# dpc5/predictdl architecture

> Architecture diagram of the GitHub repository dpc5/predictdl, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-11). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/dpc5/predictdl
- Repository: https://github.com/dpc5/predictdl

## Overview

PredictDL is a Flask-based Deadlock player and match analytics site. A visitor requests a profile or match page; the server obtains cached or upstream data, computes and assembles analytics, and renders a page. Other major branches provide hero browsing, PR leaderboards, and live-match predictions. The graph preserves the indexed core modules, but excerpts do not show every route-to-module call, so some subsystem links are omitted rather than inferred.

Main entry points: [`python/server.py`](https://github.com/dpc5/predictdl/blob/master/python/server.py) (Flask routes), [`python/cache_storage.py`](https://github.com/dpc5/predictdl/blob/master/python/cache_storage.py) (Cache storage), [`python/api.py`](https://github.com/dpc5/predictdl/blob/master/python/api.py) (Game API client), [`python/live_dashboard.py`](https://github.com/dpc5/predictdl/blob/master/python/live_dashboard.py) (Live dashboard)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_web["Web experience"]
  node_flask["Flask routes<br/>[server.py]"]
  node_templates["Page templates"]
  node_static["Browser assets"]
end

subgraph group_ingest["Game data"]
  node_api["Game API client<br/>[api.py]"]
  node_heroes["Hero catalog<br/>[hero_catalog.py]"]
  node_budget["Metadata budget<br/>[metadata_budget.py]"]
end

subgraph group_analytics["Player analytics"]
  node_rating["PR rating<br/>[player_rating.py]"]
  node_snapshot["Player snapshot<br/>[player_snapshot.py]"]
  node_insights["Player insights<br/>[player_insights.py]"]
  node_percentiles["Player percentiles"]
  node_capture["Share card renderer<br/>[capture_card.py]"]
  node_leaderboard["Official leaderboard"]
end

subgraph group_live["Live features"]
  node_liveboard["Live dashboard<br/>[live_dashboard.py]"]
  node_prediction["Live prediction<br/>[live_prediction.py]"]
  node_queue["Live player queue"]
end

subgraph group_state["Local state"]
  node_cache["Cache storage<br/>[cache_storage.py]"]
  node_playerdata[("Player cache")]
  node_matchdata[("Match cache")]
end

node_visitor(("Visitor"))
node_deadlock{{"Deadlock API"}}
node_steam{{"Steam API"}}

node_visitor -->|"requests pages"| node_flask
node_flask -->|"renders pages"| node_templates
node_flask -->|"serves assets"| node_static
node_api -->|"fetches game data"| node_deadlock
node_api -->|"fetches Steam data"| node_steam
node_api -.->|"uses cache"| node_cache
node_cache -->|"reads and writes"| node_playerdata
node_cache -->|"reads and writes"| node_matchdata
node_liveboard -.->|"computes estimates"| node_prediction
node_liveboard -->|"reads profiles"| node_cache
node_liveboard -.->|"looks up heroes"| node_heroes
node_capture -->|"builds snapshot"| node_snapshot
node_rating -->|"loads cohorts"| node_cache
node_leaderboard -->|"stores fallback"| node_cache
node_queue -->|"persists queue"| node_cache
node_flask -.->|"gets player data"| node_api
node_flask -.->|"computes PR"| node_rating
node_flask -.->|"builds insights"| node_insights
node_flask -.->|"builds percentiles"| node_percentiles
node_flask -.->|"serves live board"| node_liveboard
node_flask -.->|"serves rankings"| node_leaderboard

click node_flask "https://github.com/dpc5/predictdl/blob/master/python/server.py"
click node_templates "https://github.com/dpc5/predictdl/tree/master/templates"
click node_static "https://github.com/dpc5/predictdl/tree/master/static"
click node_api "https://github.com/dpc5/predictdl/blob/master/python/api.py"
click node_heroes "https://github.com/dpc5/predictdl/blob/master/python/hero_catalog.py"
click node_rating "https://github.com/dpc5/predictdl/blob/master/python/player_rating.py"
click node_snapshot "https://github.com/dpc5/predictdl/blob/master/python/player_snapshot.py"
click node_insights "https://github.com/dpc5/predictdl/blob/master/python/player_insights.py"
click node_percentiles "https://github.com/dpc5/predictdl/blob/master/python/player_percentiles.py"
click node_capture "https://github.com/dpc5/predictdl/blob/master/python/capture_card.py"
click node_leaderboard "https://github.com/dpc5/predictdl/blob/master/python/official_leaderboard.py"
click node_liveboard "https://github.com/dpc5/predictdl/blob/master/python/live_dashboard.py"
click node_prediction "https://github.com/dpc5/predictdl/blob/master/python/live_prediction.py"
click node_queue "https://github.com/dpc5/predictdl/blob/master/python/live_index_queue.py"
click node_budget "https://github.com/dpc5/predictdl/blob/master/python/metadata_budget.py"
click node_cache "https://github.com/dpc5/predictdl/blob/master/python/cache_storage.py"
click node_playerdata "https://github.com/dpc5/predictdl/tree/master/data"
click node_matchdata "https://github.com/dpc5/predictdl/tree/master/data"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_flask,node_templates,node_static toneBlue
class node_api,node_heroes,node_budget toneAmber
class node_rating,node_snapshot,node_insights,node_percentiles,node_capture,node_leaderboard,node_deadlock,node_steam toneMint
class node_liveboard,node_prediction,node_queue toneRose
class node_cache,node_playerdata,node_matchdata,node_visitor toneIndigo
```

## Components

### Web experience

- [Flask routes](https://github.com/dpc5/predictdl/blob/master/python/server.py): `python/server.py`
- [Page templates](https://github.com/dpc5/predictdl/tree/master/templates): `templates`
- [Browser assets](https://github.com/dpc5/predictdl/tree/master/static): `static`

### Game data

- [Game API client](https://github.com/dpc5/predictdl/blob/master/python/api.py): `python/api.py`
- [Hero catalog](https://github.com/dpc5/predictdl/blob/master/python/hero_catalog.py): `python/hero_catalog.py`
- [Metadata budget](https://github.com/dpc5/predictdl/blob/master/python/metadata_budget.py): `python/metadata_budget.py`

### Player analytics

- [PR rating](https://github.com/dpc5/predictdl/blob/master/python/player_rating.py): `python/player_rating.py`
- [Player snapshot](https://github.com/dpc5/predictdl/blob/master/python/player_snapshot.py): `python/player_snapshot.py`
- [Player insights](https://github.com/dpc5/predictdl/blob/master/python/player_insights.py): `python/player_insights.py`
- [Player percentiles](https://github.com/dpc5/predictdl/blob/master/python/player_percentiles.py): `python/player_percentiles.py`
- [Share card renderer](https://github.com/dpc5/predictdl/blob/master/python/capture_card.py): `python/capture_card.py`
- [Official leaderboard](https://github.com/dpc5/predictdl/blob/master/python/official_leaderboard.py): `python/official_leaderboard.py`

### Live features

- [Live dashboard](https://github.com/dpc5/predictdl/blob/master/python/live_dashboard.py): `python/live_dashboard.py`
- [Live prediction](https://github.com/dpc5/predictdl/blob/master/python/live_prediction.py): `python/live_prediction.py`
- [Live player queue](https://github.com/dpc5/predictdl/blob/master/python/live_index_queue.py): `python/live_index_queue.py`

### Local state

- [Cache storage](https://github.com/dpc5/predictdl/blob/master/python/cache_storage.py): `python/cache_storage.py`
- [Player cache](https://github.com/dpc5/predictdl/tree/master/data): `data`
- [Match cache](https://github.com/dpc5/predictdl/tree/master/data): `data`

### Other components

- **Visitor**
- **Deadlock API**
- **Steam API**

## Connections

- Visitor → Flask routes: requests pages (evidence: `README.md`)
- Flask routes → Page templates: renders pages (evidence: `README.md`)
- Flask routes → Browser assets: serves assets (evidence: `README.md`)
- Game API client → Deadlock API: fetches game data (evidence: `README.md`)
- Game API client → Steam API: fetches Steam data (evidence: `README.md`)
- Game API client → Cache storage: uses cache (evidence: `python/api.py`)
- Cache storage → Player cache: reads and writes (evidence: `python/cache_storage.py`)
- Cache storage → Match cache: reads and writes (evidence: `python/cache_storage.py`)
- Live dashboard → Live prediction: computes estimates (evidence: `python/live_dashboard.py`)
- Live dashboard → Cache storage: reads profiles (evidence: `python/live_dashboard.py`)
- Live dashboard → Hero catalog: looks up heroes (evidence: `python/live_dashboard.py`)
- Share card renderer → Player snapshot: builds snapshot (evidence: `python/capture_card.py`)
- PR rating → Cache storage: loads cohorts (evidence: `python/player_rating.py`)
- Official leaderboard → Cache storage: stores fallback (evidence: `python/official_leaderboard.py`)
- Live player queue → Cache storage: persists queue (evidence: `python/live_index_queue.py`)
- Flask routes → Game API client: gets player data (evidence: `python/server.py`)
- Flask routes → PR rating: computes PR (evidence: `python/server.py`)
- Flask routes → Player insights: builds insights (evidence: `python/server.py`)
- Flask routes → Player percentiles: builds percentiles (evidence: `python/server.py`)
- Flask routes → Live dashboard: serves live board (evidence: `python/server.py`)
- Flask routes → Official leaderboard: serves rankings (evidence: `python/server.py`)
