add .gitignore
This commit is contained in:
4 files changed
+2
-570
No files matched your search
+1
-2
@@ -31,5 +31,4 @@ data.csv
|
|||||||
# Docker itself
|
# Docker itself
|
||||||
Dockerfile
|
Dockerfile
|
||||||
docker-compose.yml
|
docker-compose.yml
|
||||||
.dockerignore
|
.dockerignore
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
.idea
|
.idea
|
||||||
.venv
|
.venv
|
||||||
|
dist/
|
||||||
|
|
||||||
__pycache__/
|
__pycache__/
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
# AGENTS.md — The Hope Pub Quiz Dashboard
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
Single-page Flask dashboard that reads `data.csv` (one row per quiz night) and renders summary statistics, a player cost table, and five Plotly charts via a Jinja2 template. No database — the CSV is the sole data store.
|
|
||||||
|
|
||||||
## Running the App
|
|
||||||
```bash
|
|
||||||
uv sync # install deps from uv.lock / pyproject.toml
|
|
||||||
PYTHONPATH=src python src/app.py # run from project root — resolves data.csv correctly
|
|
||||||
```
|
|
||||||
> **Path gotcha:** `app.py` reads `data.csv` with a bare relative path, so the CWD must be the **project root**. `PYTHONPATH=src` puts `src/` on the import path so local modules resolve.
|
|
||||||
|
|
||||||
## Data Shape (`data.csv`)
|
|
||||||
- **One row = one quiz night**
|
|
||||||
- Columns: `Date` (DD/MM/YYYY), `Absolute Position`, `Relative Position` (float 0–1, 0=1st/best, 1=last), `Number of Players`, `Number of Teams`, `Points on Scattergories`, then one binary column per player (1=attended, 0=absent).
|
|
||||||
- Date parsing uses `dayfirst=True`; the DataFrame is sorted ascending by date on every load.
|
|
||||||
|
|
||||||
## Module Responsibilities
|
|
||||||
| File | Role |
|
|
||||||
|---|---|
|
|
||||||
| `src/app.py` | Flask route, five Plotly chart builders, data loading |
|
|
||||||
| `src/stats.py` | `generate_stats(df)` → `(stats_dict, highlights_list)` tuple |
|
|
||||||
| `src/player_table.py` | `generate_player_table(df)` → flat list-of-lists; cost hard-coded at **£3/quiz** |
|
|
||||||
| `src/constants.py` | Player names, regression features, colour scheme, `ordinal(n)` helper |
|
|
||||||
| `src/templates/index.html` | Renders `highlights` list, `stats` dict, `player_table`, and `plots` dict |
|
|
||||||
|
|
||||||
## Key Conventions
|
|
||||||
|
|
||||||
### Adding/Removing a Player
|
|
||||||
1. Update `constants.PLAYER_NAME_COLUMNS` (ordered list — controls display order everywhere).
|
|
||||||
2. Update `constants.FEATURE_COLUMNS` (set — controls which columns feed the regression model).
|
|
||||||
3. Add the new binary column to `data.csv`.
|
|
||||||
|
|
||||||
### `generate_stats` Return Value
|
|
||||||
Returns a **tuple** `(stats, highlights)`:
|
|
||||||
- `highlights` — list of `{"label": str, "value": str, "detail": str}` dicts; rendered as 6 KPI cards.
|
|
||||||
- `stats` — plain `dict` of human-readable `label: value` pairs; rendered as a secondary list.
|
|
||||||
|
|
||||||
The `index()` route unpacks both: `stats, highlights = generate_stats(df)`.
|
|
||||||
|
|
||||||
### Plots Pipeline
|
|
||||||
1. Build a Plotly figure in `app.py` using `Relative Position` directly (or `Relative Position * 100` for percentile display), where **lower = better**.
|
|
||||||
2. Serialise: `json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder)`.
|
|
||||||
3. Store in the `plots` dict under a **snake_case key** (e.g. `"position_trend"`).
|
|
||||||
4. The template renders every entry automatically: `Plotly.newPlot("{{ key }}", ...)` — key is both the `<div id>` and JS target.
|
|
||||||
|
|
||||||
Current charts (in render order): `position_trend`, `player_impact`, `scattergories_vs_position`, `player_participation`, `calendar`.
|
|
||||||
|
|
||||||
### `player_table` Structure
|
|
||||||
`[0]` = header row, `[1:-1]` = data rows sorted by appearances descending, `[-1]` = totals footer. The template uses `player_table[1:-1]` for `<tbody>` and `player_table[-1]` for `<tfoot>`.
|
|
||||||
|
|
||||||
### `Relative Position` Convention
|
|
||||||
Raw data stores `Relative Position` (0=best). The dashboard keeps this convention everywhere: lower values are better in stats, tables, and chart labels. If a chart uses percentile text, it is `Relative Position * 100` (still lower = better).
|
|
||||||
|
|
||||||
### `ordinal(n)` Helper
|
|
||||||
Lives in `constants.py`. Returns e.g. `"1st"`, `"22nd"`, `"63rd"`. Import where needed: `from constants import ordinal`.
|
|
||||||
|
|
||||||
### Player Impact Chart
|
|
||||||
Shows average relative percentile when each player attends. Only players with **>= 3 appearances** are shown (`MIN_APPEARANCES = 3` in `generate_player_impact`). Green bar = below overall average (better); red = above (worse).
|
|
||||||
|
|
||||||
## Frontend
|
|
||||||
No build step. Tailwind CSS (`cdn.tailwindcss.com`) and Plotly (`cdn.plot.ly/plotly-3.0.1.min.js`) loaded from CDN. Charts use `{ responsive: true, displayModeBar: false }` config.
|
|
||||||
Vendored
-506
@@ -1,506 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>The Hope Pub Quiz</title>
|
|
||||||
<script src="https://cdn.plot.ly/plotly-3.0.1.min.js" charset="utf-8"></script>
|
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body class="bg-gray-50 min-h-screen text-gray-900 antialiased">
|
|
||||||
|
|
||||||
<!-- ── Header ─────────────────────────────────────────────────────────── -->
|
|
||||||
<header class="bg-blue-900 text-white shadow-lg">
|
|
||||||
<div class="max-w-6xl mx-auto px-4 sm:px-8 py-8 sm:py-10">
|
|
||||||
<p class="text-blue-300 text-xs font-semibold tracking-widest uppercase mb-2">Performance Dashboard</p>
|
|
||||||
<h1 class="text-3xl sm:text-4xl font-bold tracking-tight">The Hope Pub Quiz</h1>
|
|
||||||
<p class="text-blue-300 mt-2 text-sm">Trying to convince ourselves we're not stupid</p>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main class="max-w-6xl mx-auto px-4 sm:px-8 py-10 space-y-14">
|
|
||||||
|
|
||||||
<!-- ── KPI Cards ───────────────────────────────────────────────────── -->
|
|
||||||
<section>
|
|
||||||
<h2 class="text-xs font-semibold tracking-widest uppercase text-gray-400 mb-5">At a Glance</h2>
|
|
||||||
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-4">
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-5 flex flex-col gap-1">
|
|
||||||
<span class="text-3xl font-bold text-blue-900 leading-none">23</span>
|
|
||||||
<span class="text-sm font-medium text-gray-700 mt-2">Quizzes Played</span>
|
|
||||||
<span class="text-xs text-gray-400 leading-snug">Since Mar 2025</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-5 flex flex-col gap-1">
|
|
||||||
<span class="text-3xl font-bold text-blue-900 leading-none">61st</span>
|
|
||||||
<span class="text-sm font-medium text-gray-700 mt-2">Avg. Relative Percentile</span>
|
|
||||||
<span class="text-xs text-gray-400 leading-snug">Lower = better finishing position</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-5 flex flex-col gap-1">
|
|
||||||
<span class="text-3xl font-bold text-blue-900 leading-none">4th place</span>
|
|
||||||
<span class="text-sm font-medium text-gray-700 mt-2">Best Finish</span>
|
|
||||||
<span class="text-xs text-gray-400 leading-snug">Out of 12 teams</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-5 flex flex-col gap-1">
|
|
||||||
<span class="text-3xl font-bold text-blue-900 leading-none">68th</span>
|
|
||||||
<span class="text-sm font-medium text-gray-700 mt-2">Recent Form</span>
|
|
||||||
<span class="text-xs text-gray-400 leading-snug">↑ declining vs overall (lower is better)</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-5 flex flex-col gap-1">
|
|
||||||
<span class="text-3xl font-bold text-blue-900 leading-none">5</span>
|
|
||||||
<span class="text-sm font-medium text-gray-700 mt-2">Top-Half Finishes</span>
|
|
||||||
<span class="text-xs text-gray-400 leading-snug">22% of all games</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-5 flex flex-col gap-1">
|
|
||||||
<span class="text-3xl font-bold text-blue-900 leading-none">4 wks</span>
|
|
||||||
<span class="text-sm font-medium text-gray-700 mt-2">Best Streak</span>
|
|
||||||
<span class="text-xs text-gray-400 leading-snug">Consecutive weeks attended</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- ── Stats + Squad Table ─────────────────────────────────────────── -->
|
|
||||||
<section class="grid grid-cols-1 lg:grid-cols-2 gap-8 items-start">
|
|
||||||
|
|
||||||
<!-- Secondary stats -->
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-6">
|
|
||||||
<h2 class="text-xs font-semibold tracking-widest uppercase text-gray-400 mb-5">More Stats</h2>
|
|
||||||
<dl class="divide-y divide-gray-50">
|
|
||||||
|
|
||||||
<div class="flex justify-between items-baseline py-3 first:pt-0 last:pb-0">
|
|
||||||
<dt class="text-sm text-gray-500">Top-half finishes</dt>
|
|
||||||
<dd class="text-sm font-semibold text-gray-900 ml-4 text-right">5 of 23 (22%)</dd>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-baseline py-3 first:pt-0 last:pb-0">
|
|
||||||
<dt class="text-sm text-gray-500">Average teams per night</dt>
|
|
||||||
<dd class="text-sm font-semibold text-gray-900 ml-4 text-right">11.8</dd>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-baseline py-3 first:pt-0 last:pb-0">
|
|
||||||
<dt class="text-sm text-gray-500">Average squad size</dt>
|
|
||||||
<dd class="text-sm font-semibold text-gray-900 ml-4 text-right">2.9 players</dd>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-baseline py-3 first:pt-0 last:pb-0">
|
|
||||||
<dt class="text-sm text-gray-500">Average Scattergories score</dt>
|
|
||||||
<dd class="text-sm font-semibold text-gray-900 ml-4 text-right">6.9 pts</dd>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-baseline py-3 first:pt-0 last:pb-0">
|
|
||||||
<dt class="text-sm text-gray-500">Best Scattergories score</dt>
|
|
||||||
<dd class="text-sm font-semibold text-gray-900 ml-4 text-right">11 pts</dd>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex justify-between items-baseline py-3 first:pt-0 last:pb-0">
|
|
||||||
<dt class="text-sm text-gray-500">Longest individual streak</dt>
|
|
||||||
<dd class="text-sm font-semibold text-gray-900 ml-4 text-right">14 weeks (Jay)</dd>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Squad table -->
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-6 overflow-x-auto">
|
|
||||||
<h2 class="text-xs font-semibold tracking-widest uppercase text-gray-400 mb-5">Squad</h2>
|
|
||||||
<table class="w-full text-sm">
|
|
||||||
<thead>
|
|
||||||
<tr class="border-b-2 border-gray-100">
|
|
||||||
|
|
||||||
<th class="pb-3 text-xs font-semibold text-gray-400 uppercase tracking-wider
|
|
||||||
text-left">
|
|
||||||
Player
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th class="pb-3 text-xs font-semibold text-gray-400 uppercase tracking-wider
|
|
||||||
text-right">
|
|
||||||
Appearances
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th class="pb-3 text-xs font-semibold text-gray-400 uppercase tracking-wider
|
|
||||||
text-right">
|
|
||||||
Avg. Relative Percentile
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th class="pb-3 text-xs font-semibold text-gray-400 uppercase tracking-wider
|
|
||||||
text-right">
|
|
||||||
Spent
|
|
||||||
</th>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="divide-y divide-gray-50">
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Jay
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
22
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
62nd
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£66.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Ciaran
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
20
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
62nd
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£60.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Sam
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
9
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
59th
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£27.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Ellora
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
5
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
52nd
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£15.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Drew
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
3
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
56th
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£9.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Tom
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
2
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
62nd
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£6.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Chloe
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
2
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
75th
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£6.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Theo
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
1
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
50th
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£3.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Jamie
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
1
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
50th
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£3.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Christine
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
1
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
50th
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£3.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
<tr class="hover:bg-gray-50 transition-colors">
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-left font-medium text-gray-800">
|
|
||||||
Mide
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
1
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
100th
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-3
|
|
||||||
text-right text-gray-500">
|
|
||||||
£3.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr class="border-t-2 border-gray-200">
|
|
||||||
|
|
||||||
<td class="pt-3 font-bold text-gray-700
|
|
||||||
text-left">
|
|
||||||
Total
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="pt-3 font-bold text-gray-700
|
|
||||||
text-right">
|
|
||||||
67
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="pt-3 font-bold text-gray-700
|
|
||||||
text-right">
|
|
||||||
—
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="pt-3 font-bold text-gray-700
|
|
||||||
text-right">
|
|
||||||
£201.00
|
|
||||||
</td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- ── Charts ──────────────────────────────────────────────────────── -->
|
|
||||||
<section>
|
|
||||||
<h2 class="text-xs font-semibold tracking-widest uppercase text-gray-400 mb-5">Charts</h2>
|
|
||||||
<div class="space-y-8">
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-4 sm:p-6">
|
|
||||||
<div id="position_trend"></div>
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
var figure = {"data": [{"customdata": ["Ciaran, Jay", "Ciaran, Jay", "Ciaran, Jay, Sam, Drew", "Ciaran, Jay", "Ciaran, Jay, Sam", "Jay, Theo", "Ciaran, Jay, Sam", "Ciaran, Jay, Sam", "Ciaran, Jay, Sam, Tom", "Ciaran, Jay, Ellora", "Ciaran, Jay", "Ciaran, Jay, Sam, Ellora", "Ciaran, Jay, Ellora", "Ciaran, Jay, Sam, Ellora", "Ciaran, Sam, Tom", "Jay, Drew", "Ciaran, Jay, Ellora", "Ciaran, Jay, Chloe, Jamie", "Ciaran, Jay", "Ciaran, Jay", "Jay, Drew, Christine", "Ciaran, Jay", "Ciaran, Jay, Sam, Chloe, Mide"], "hovertemplate": "<b>%{x|%d %b %Y}</b><br>Relative percentile: %{y:.0f}th<br>Squad: %{customdata}<extra></extra>", "line": {"color": "#1e3a8a", "width": 1.5}, "marker": {"color": "#1e3a8a", "size": 6}, "mode": "lines+markers", "name": "Result", "x": ["2025-03-17T00:00:00.000000000", "2025-03-24T00:00:00.000000000", "2025-03-31T00:00:00.000000000", "2025-04-07T00:00:00.000000000", "2025-04-28T00:00:00.000000000", "2025-05-26T00:00:00.000000000", "2025-06-02T00:00:00.000000000", "2025-06-16T00:00:00.000000000", "2025-06-30T00:00:00.000000000", "2025-07-14T00:00:00.000000000", "2025-07-21T00:00:00.000000000", "2025-07-28T00:00:00.000000000", "2025-08-04T00:00:00.000000000", "2025-09-15T00:00:00.000000000", "2025-09-22T00:00:00.000000000", "2025-09-29T00:00:00.000000000", "2025-11-24T00:00:00.000000000", "2026-01-05T00:00:00.000000000", "2026-01-26T00:00:00.000000000", "2026-02-02T00:00:00.000000000", "2026-02-16T00:00:00.000000000", "2026-02-23T00:00:00.000000000", "2026-03-09T00:00:00.000000000"], "y": {"dtype": "f8", "bdata": "zMzMzMxMUUA0MzMzM1NXQDMzMzMzM0ZAZmZmZmYmTEA0MzMzM3NKQAAAAAAAAElAzczMzMxsVUABAAAAAEBLQDMzMzMz01RAAAAAAABAT0AAAAAAAABJQAAAAAAAwEJAAAAAAAAAREBnZmZmZqZAQJmZmZmZ2URAzczMzMwsUkCamZmZmTlWQAAAAAAAAElAZmZmZmYmTUAAAAAAAIBRQAAAAAAAAElAAAAAAAAATkAAAAAAAABZQA=="}, "type": "scatter"}, {"hovertemplate": "<b>%{x|%d %b %Y}</b><br>5-Game Avg: %{y:.0f}%<extra></extra>", "line": {"color": "#f59e0b", "width": 2.5}, "mode": "lines", "name": "5-Game Avg", "x": ["2025-03-17T00:00:00.000000000", "2025-03-24T00:00:00.000000000", "2025-03-31T00:00:00.000000000", "2025-04-07T00:00:00.000000000", "2025-04-28T00:00:00.000000000", "2025-05-26T00:00:00.000000000", "2025-06-02T00:00:00.000000000", "2025-06-16T00:00:00.000000000", "2025-06-30T00:00:00.000000000", "2025-07-14T00:00:00.000000000", "2025-07-21T00:00:00.000000000", "2025-07-28T00:00:00.000000000", "2025-08-04T00:00:00.000000000", "2025-09-15T00:00:00.000000000", "2025-09-22T00:00:00.000000000", "2025-09-29T00:00:00.000000000", "2025-11-24T00:00:00.000000000", "2026-01-05T00:00:00.000000000", "2026-01-26T00:00:00.000000000", "2026-02-02T00:00:00.000000000", "2026-02-16T00:00:00.000000000", "2026-02-23T00:00:00.000000000", "2026-03-09T00:00:00.000000000"], "y": {"dtype": "f8", "bdata": "zMzMzMxMUUAAAAAAAFBUQN7d3d3dPVFAMzMzMzNzUEBdj8L1KJxPQHI9CtejsE1ArkfhehTuTEByPQrXo/BNQFK4HoXrUVBAzczMzMzMUEDNzMzMzMxQQEjhehSux0xAFa5H4XpUS0AVrkfhelRGQAAAAAAAQERAhetRuB6FRkAqXI/C9ahLQCpcj8L1qExAKlyPwvUoT0AehetRuP5QQLoehetRuE9AE65H4XrUTEAK16NwPepQQA=="}, "type": "scatter"}, {"hoverinfo": "skip", "line": {"color": "#dc2626", "dash": "dot", "width": 1.5}, "mode": "lines", "name": "Trend", "x": ["2025-03-17", "2025-03-18", "2025-03-20", "2025-03-22", "2025-03-24", "2025-03-25", "2025-03-27", "2025-03-29", "2025-03-31", "2025-04-02", "2025-04-03", "2025-04-05", "2025-04-07", "2025-04-09", "2025-04-11", "2025-04-12", "2025-04-14", "2025-04-16", "2025-04-18", "2025-04-20", "2025-04-21", "2025-04-23", "2025-04-25", "2025-04-27", "2025-04-29", "2025-04-30", "2025-05-02", "2025-05-04", "2025-05-06", "2025-05-08", "2025-05-09", "2025-05-11", "2025-05-13", "2025-05-15", "2025-05-16", "2025-05-18", "2025-05-20", "2025-05-22", "2025-05-24", "2025-05-25", "2025-05-27", "2025-05-29", "2025-05-31", "2025-06-02", "2025-06-03", "2025-06-05", "2025-06-07", "2025-06-09", "2025-06-11", "2025-06-12", "2025-06-14", "2025-06-16", "2025-06-18", "2025-06-20", "2025-06-21", "2025-06-23", "2025-06-25", "2025-06-27", "2025-06-29", "2025-06-30", "2025-07-02", "2025-07-04", "2025-07-06", "2025-07-08", "2025-07-09", "2025-07-11", "2025-07-13", "2025-07-15", "2025-07-16", "2025-07-18", "2025-07-20", "2025-07-22", "2025-07-24", "2025-07-25", "2025-07-27", "2025-07-29", "2025-07-31", "2025-08-02", "2025-08-03", "2025-08-05", "2025-08-07", "2025-08-09", "2025-08-11", "2025-08-12", "2025-08-14", "2025-08-16", "2025-08-18", "2025-08-20", "2025-08-21", "2025-08-23", "2025-08-25", "2025-08-27", "2025-08-29", "2025-08-30", "2025-09-01", "2025-09-03", "2025-09-05", "2025-09-07", "2025-09-08", "2025-09-10", "2025-09-12", "2025-09-14", "2025-09-15", "2025-09-17", "2025-09-19", "2025-09-21", "2025-09-23", "2025-09-24", "2025-09-26", "2025-09-28", "2025-09-30", "2025-10-02", "2025-10-03", "2025-10-05", "2025-10-07", "2025-10-09", "2025-10-11", "2025-10-12", "2025-10-14", "2025-10-16", "2025-10-18", "2025-10-20", "2025-10-21", "2025-10-23", "2025-10-25", "2025-10-27", "2025-10-29", "2025-10-30", "2025-11-01Line truncated
|
|
||||||
Plotly.newPlot("position_trend", figure.data, figure.layout, { responsive: true, displayModeBar: false });
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-4 sm:p-6">
|
|
||||||
<div id="player_impact"></div>
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
var figure = {"data": [{"hovertemplate": "<b>%{y}</b><br>Avg relative percentile: %{x:.1f}th<extra></extra>", "marker": {"color": ["#16a34a", "#16a34a", "#16a34a", "#dc2626", "#dc2626"]}, "orientation": "h", "text": ["52nd (5 games)", "56th (3 games)", "59th (9 games)", "62nd (20 games)", "62nd (22 games)"], "textposition": "outside", "x": {"dtype": "f8", "bdata": "MzMzMzMzSkCamZmZmdlLQGZmZmZmpk1AzczMzMzMTkAzMzMzM/NOQA=="}, "y": ["Ellora", "Drew", "Sam", "Ciaran", "Jay"], "type": "bar"}], "layout": {"template": {"data": {"barpolar": [{"marker": {"line": {"color": "white", "width": 0.5}, "pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "barpolar"}], "bar": [{"error_x": {"color": "#2a3f5f"}, "error_y": {"color": "#2a3f5f"}, "marker": {"line": {"color": "white", "width": 0.5}, "pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "bar"}], "carpet": [{"aaxis": {"endlinecolor": "#2a3f5f", "gridcolor": "#C8D4E3", "linecolor": "#C8D4E3", "minorgridcolor": "#C8D4E3", "startlinecolor": "#2a3f5f"}, "baxis": {"endlinecolor": "#2a3f5f", "gridcolor": "#C8D4E3", "linecolor": "#C8D4E3", "minorgridcolor": "#C8D4E3", "startlinecolor": "#2a3f5f"}, "type": "carpet"}], "choropleth": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "choropleth"}], "contourcarpet": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "contourcarpet"}], "contour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "contour"}], "heatmap": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "heatmap"}], "histogram2dcontour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2dcontour"}], "histogram2d": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2d"}], "histogram": [{"marker": {"pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "histogram"}], "mesh3d": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "mesh3d"}], "parcoords": [{"line": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "parcoords"}], "pie": [{"automargin": true, "type": "pie"}], "scatter3d": [{"line": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatter3d"}], "scattercarpet": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattercarpet"}], "scattergeo": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattergeo"}], "scattergl": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattergl"}], "scattermapbox": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattermapbox"}], "scattermap": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattermap"}], "scatterpolargl": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatterpolargl"}], "scatterpolar": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatterpolar"}], "scatter": [{"fillpattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}, "type": "scatter"}], "scatterternary": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatterternary"}], "surface": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "surface"}], "table": [{"cells": {"fill": {"color": "#EBF0F8"}, "line": {"color": "white"}}, "header": {"fill": {"color": "#C8D4E3"}, "line": {"color": "white"}}, "type": "table"}]}, "layoutLine truncated
|
|
||||||
Plotly.newPlot("player_impact", figure.data, figure.layout, { responsive: true, displayModeBar: false });
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-4 sm:p-6">
|
|
||||||
<div id="scattergories_vs_position"></div>
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
var figure = {"data": [{"hovertemplate": "Scattergories Points=%{x}<br>Relative Position Percentile (lower is better)=%{y:.1f}<extra></extra>", "legendgroup": "", "marker": {"color": "#1e3a8a", "symbol": "circle", "opacity": 0.8, "size": 9}, "mode": "markers", "name": "", "orientation": "v", "showlegend": false, "x": {"dtype": "i1", "bdata": "CgQHBgUIBAYICAkECwUFBQYGCgUGCgo="}, "xaxis": "x", "y": {"dtype": "f8", "bdata": "zMzMzMxMUUA0MzMzM1NXQDMzMzMzM0ZAZmZmZmYmTEA0MzMzM3NKQAAAAAAAAElAzczMzMxsVUABAAAAAEBLQDMzMzMz01RAAAAAAABAT0AAAAAAAABJQAAAAAAAwEJAAAAAAAAAREBnZmZmZqZAQJmZmZmZ2URAzczMzMwsUkCamZmZmTlWQAAAAAAAAElAZmZmZmYmTUAAAAAAAIBRQAAAAAAAAElAAAAAAAAATkAAAAAAAABZQA=="}, "yaxis": "y", "type": "scatter"}, {"hovertemplate": "<b>OLS trendline</b><br>Relative Percentile = 0.100314 * Points on Scattergories + 60.3761<br>R<sup>2</sup>=0.000143<br><br>Scattergories Points=%{x}<br>Relative Position Percentile (lower is better)=%{y:.1f} <b>(trend)</b><extra></extra>", "legendgroup": "", "marker": {"color": "#636efa", "symbol": "circle"}, "mode": "lines", "name": "", "showlegend": false, "x": {"dtype": "i1", "bdata": "BAQEBQUFBQUGBgYGBgcICAgJCgoKCgs="}, "xaxis": "x", "y": {"dtype": "f8", "bdata": "3h+ne4BjTkDeH6d7gGNOQN4fp3uAY05AbD9hlldwTkBsP2GWV3BOQGw/YZZXcE5AbD9hlldwTkBsP2GWV3BOQPpeG7EufU5A+l4bsS59TkD6XhuxLn1OQPpeG7EufU5A+l4bsS59TkCIftXLBYpOQBaej+bclk5AFp6P5tyWTkAWno/m3JZOQKS9SQG0o05AMd0DHIuwTkAx3QMci7BOQDHdAxyLsE5AMd0DHIuwTkC//L02Yr1OQA=="}, "yaxis": "y", "type": "scatter", "line": {"color": "#dc2626", "dash": "dot", "width": 2}}], "layout": {"template": {"data": {"barpolar": [{"marker": {"line": {"color": "white", "width": 0.5}, "pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "barpolar"}], "bar": [{"error_x": {"color": "#2a3f5f"}, "error_y": {"color": "#2a3f5f"}, "marker": {"line": {"color": "white", "width": 0.5}, "pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "bar"}], "carpet": [{"aaxis": {"endlinecolor": "#2a3f5f", "gridcolor": "#C8D4E3", "linecolor": "#C8D4E3", "minorgridcolor": "#C8D4E3", "startlinecolor": "#2a3f5f"}, "baxis": {"endlinecolor": "#2a3f5f", "gridcolor": "#C8D4E3", "linecolor": "#C8D4E3", "minorgridcolor": "#C8D4E3", "startlinecolor": "#2a3f5f"}, "type": "carpet"}], "choropleth": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "choropleth"}], "contourcarpet": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "contourcarpet"}], "contour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "contour"}], "heatmap": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "heatmap"}], "histogram2dcontour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2dcontour"}], "histogram2d": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2d"}], "histogram": [{"marker": {"pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "histogram"}], "mesh3d": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "mesh3d"}], "parcoords": [{"line": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "parcoords"}], "pie": [{"automargin": true, "type": "pie"}], "scatter3d": [{"line": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatter3d"}], "scattercarpet": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattercarpet"}], "scattergeo": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattergeo"}], "scattergl": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattergl"}], "scattermapbox": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattermapbox"}], "scattermap": [{"marker": {"colorbar":Line truncated
|
|
||||||
Plotly.newPlot("scattergories_vs_position", figure.data, figure.layout, { responsive: true, displayModeBar: false });
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-4 sm:p-6">
|
|
||||||
<div id="player_participation"></div>
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
var figure = {"data": [{"coloraxis": "coloraxis", "name": "0", "x": {"dtype": "i1", "bdata": "AAECAwQFBgcICQoLDA0ODxAREhMUFRY="}, "y": ["Ciaran", "Jay", "Sam", "Drew", "Theo", "Tom", "Ellora", "Chloe", "Jamie", "Christine", "Mide"], "z": {"dtype": "i1", "bdata": "AQEBAQEAAQEBAQEBAQEBAAEBAQEAAQEBAQEBAQEBAQEBAQEBAQABAQEBAQEBAQAAAQABAAEBAQAAAQABAQAAAAAAAAABAAABAAAAAAAAAAAAAAAAAQAAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAQABAQEAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ==", "shape": "11, 23"}, "type": "heatmap", "xaxis": "x", "yaxis": "y", "hovertemplate": "Game: %{x}<br>Player: %{y}<br>Attended: %{z}<extra></extra>"}], "layout": {"template": {"data": {"barpolar": [{"marker": {"line": {"color": "white", "width": 0.5}, "pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "barpolar"}], "bar": [{"error_x": {"color": "#2a3f5f"}, "error_y": {"color": "#2a3f5f"}, "marker": {"line": {"color": "white", "width": 0.5}, "pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "bar"}], "carpet": [{"aaxis": {"endlinecolor": "#2a3f5f", "gridcolor": "#C8D4E3", "linecolor": "#C8D4E3", "minorgridcolor": "#C8D4E3", "startlinecolor": "#2a3f5f"}, "baxis": {"endlinecolor": "#2a3f5f", "gridcolor": "#C8D4E3", "linecolor": "#C8D4E3", "minorgridcolor": "#C8D4E3", "startlinecolor": "#2a3f5f"}, "type": "carpet"}], "choropleth": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "choropleth"}], "contourcarpet": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "contourcarpet"}], "contour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "contour"}], "heatmap": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "heatmap"}], "histogram2dcontour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2dcontour"}], "histogram2d": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2d"}], "histogram": [{"marker": {"pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "histogram"}], "mesh3d": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "mesh3d"}], "parcoords": [{"line": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "parcoords"}], "pie": [{"automargin": true, "type": "pie"}], "scatter3d": [{"line": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatter3d"}], "scattercarpet": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattercarpet"}], "scattergeo": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattergeo"}], "scattergl": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattergl"}], "scattermapbox": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattermapbox"}], "scattermap": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scattermap"}], "scatterpolargl": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatterpolargl"}], "scatterpolar": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatterpolar"}], "scatter": [{"fillpattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}, "type": "scatter"}], "scatterternary": [{"marker": {"colorbar": {"outlinewidth": 0, "ticks": ""}}, "type": "scatterternary"}], "surface": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9Line truncated
|
|
||||||
Plotly.newPlot("player_participation", figure.data, figure.layout, { responsive: true, displayModeBar: false });
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="bg-white rounded-xl border border-gray-100 shadow-sm p-4 sm:p-6">
|
|
||||||
<div id="calendar"></div>
|
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
var figure = {"data": [{"colorscale": [[0, "#E4ECF6"], [1, "#1e3a8a"]], "hovertemplate": "%{y}<br>Column %{x}<br>%{text}<br>Attended: %{z}<extra></extra>", "showscale": false, "text": [["ISO week 1", "ISO week 2", "ISO week 3", "ISO week 4", "ISO week 5", "ISO week 6", "ISO week 7", "ISO week 8", "ISO week 9", "ISO week 10", "ISO week 11", "ISO week 12", "ISO week 13"], ["ISO week 14", "ISO week 15", "ISO week 16", "ISO week 17", "ISO week 18", "ISO week 19", "ISO week 20", "ISO week 21", "ISO week 22", "ISO week 23", "ISO week 24", "ISO week 25", "ISO week 26"], ["ISO week 27", "ISO week 28", "ISO week 29", "ISO week 30", "ISO week 31", "ISO week 32", "ISO week 33", "ISO week 34", "ISO week 35", "ISO week 36", "ISO week 37", "ISO week 38", "ISO week 39"], ["ISO week 40", "ISO week 41", "ISO week 42", "ISO week 43", "ISO week 44", "ISO week 45", "ISO week 46", "ISO week 47", "ISO week 48", "ISO week 49", "ISO week 50", "ISO week 51", "ISO week 52"], ["ISO week 1", "ISO week 2", "ISO week 3", "ISO week 4", "ISO week 5", "ISO week 6", "ISO week 7", "ISO week 8", "ISO week 9", "ISO week 10", "ISO week 11", "ISO week 12", "ISO week 13"], ["ISO week 14", "ISO week 15", "ISO week 16", "ISO week 17", "ISO week 18", "ISO week 19", "ISO week 20", "ISO week 21", "ISO week 22", "ISO week 23", "ISO week 24", "ISO week 25", "ISO week 26"], ["ISO week 27", "ISO week 28", "ISO week 29", "ISO week 30", "ISO week 31", "ISO week 32", "ISO week 33", "ISO week 34", "ISO week 35", "ISO week 36", "ISO week 37", "ISO week 38", "ISO week 39"], ["ISO week 40", "ISO week 41", "ISO week 42", "ISO week 43", "ISO week 44", "ISO week 45", "ISO week 46", "ISO week 47", "ISO week 48", "ISO week 49", "ISO week 50", "ISO week 51", "ISO week 52"]], "x": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], "xgap": 3, "y": ["2025 \u00b7 W1-13", "2025 \u00b7 W14-26", "2025 \u00b7 W27-39", "2025 \u00b7 W40-52", "2026 \u00b7 W1-13", "2026 \u00b7 W14-26", "2026 \u00b7 W27-39", "2026 \u00b7 W40-52"], "ygap": 3, "z": [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], [1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], "zmax": 1, "zmin": 0, "type": "heatmap"}], "layout": {"template": {"data": {"barpolar": [{"marker": {"line": {"color": "white", "width": 0.5}, "pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "barpolar"}], "bar": [{"error_x": {"color": "#2a3f5f"}, "error_y": {"color": "#2a3f5f"}, "marker": {"line": {"color": "white", "width": 0.5}, "pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type": "bar"}], "carpet": [{"aaxis": {"endlinecolor": "#2a3f5f", "gridcolor": "#C8D4E3", "linecolor": "#C8D4E3", "minorgridcolor": "#C8D4E3", "startlinecolor": "#2a3f5f"}, "baxis": {"endlinecolor": "#2a3f5f", "gridcolor": "#C8D4E3", "linecolor": "#C8D4E3", "minorgridcolor": "#C8D4E3", "startlinecolor": "#2a3f5f"}, "type": "carpet"}], "choropleth": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "choropleth"}], "contourcarpet": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "type": "contourcarpet"}], "contour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "contour"}], "heatmap": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "heatmap"}], "histogram2dcontour": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2dcontour"}], "histogram2d": [{"colorbar": {"outlinewidth": 0, "ticks": ""}, "colorscale": [[0.0, "#0d0887"], [0.1111111111111111, "#46039f"], [0.2222222222222222, "#7201a8"], [0.3333333333333333, "#9c179e"], [0.4444444444444444, "#bd3786"], [0.5555555555555556, "#d8576b"], [0.6666666666666666, "#ed7953"], [0.7777777777777778, "#fb9f3a"], [0.8888888888888888, "#fdca26"], [1.0, "#f0f921"]], "type": "histogram2d"}], "histogram": [{"marker": {"pattern": {"fillmode": "overlay", "size": 10, "solidity": 0.2}}, "type":Line truncated
|
|
||||||
Plotly.newPlot("calendar", figure.data, figure.layout, { responsive: true, displayModeBar: false });
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</main>
|
|
||||||
|
|
||||||
<!-- ── Footer ─────────────────────────────────────────────────────────── -->
|
|
||||||
<footer class="mt-16 border-t border-gray-200 bg-white">
|
|
||||||
<div class="max-w-6xl mx-auto px-4 sm:px-8 py-5 flex flex-col sm:flex-row justify-between items-center gap-2 text-xs text-gray-400">
|
|
||||||
<span>The Hope Pub Quiz Dashboard</span>
|
|
||||||
<span>23 quizzes · 5 charts</span>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
Reference in new issue
Block a user