Metadata-Version: 2.4
Name: campos-football
Version: 0.1.0rc2
Summary: Beautiful, battle-tested football UI components for Python.
Author: withqwerty
License: MIT
Keywords: football,soccer,visualization,matplotlib,xG,scouting
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: matplotlib>=3.7
Requires-Dist: mplsoccer>=1.2
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-mpl>=0.16; extra == "dev"
Requires-Dist: datamodel-code-generator>=0.25; extra == "dev"

# Campos

Beautiful, battle-tested football UI components for Python.

Campos gives you production-quality football visualisations with minimal code. Pass in your data, get back a matplotlib figure. No styling code required.

```python
from campos import shot_map, use_theme
from campos.schema import Shot

use_theme("dark")

shots = [
    Shot(id="1", xg=0.72, x=0.9, y=0.5, outcome="goal", body_part="foot"),
    Shot(id="2", xg=0.11, x=0.75, y=0.3, outcome="saved", body_part="head"),
    Shot(id="3", xg=0.45, x=0.88, y=0.6, outcome="goal", body_part="foot"),
]

fig = shot_map(shots, title="Salah vs Arsenal")
fig.savefig("shots.png", dpi=150, bbox_inches="tight")
```

## Install

```bash
pip install campos-football
```

Requires Python 3.10+.

## Components

| Component | What it does | Example |
|-----------|-------------|---------|
| `shot_map` | Half-pitch shot plot with xG sizing, body-part shapes, outcome colours | `shot_map(shots, title="xG Map")` |
| `radar_chart` | Polar radar with comparison polygon and reversed-scale support | `radar_chart(categories, comparison_label="League avg")` |
| `player_table` | Sortable table with colour-scaled metric cells | `player_table(players, metrics, sort_by="Goals")` |
| `percentile_ribbon` | Horizontal percentile bars with comparison overlay | `percentile_ribbon(rows, comparison_label="Median")` |
| `percentile_group` | Category header + aggregate score + nested ribbon | `percentile_group("Shooting", rows, aggregate_score=88)` |
| `category_score_card` | Small tile with score, comparison delta, progress arc | `category_score_card("Creation", 91, comparison_score=72)` |
| `ranked_list` | Leaderboard with rank, name, and value bars | `ranked_list(items, title="Top Scorers")` |
| `player_hero` | Player card with name, position pill, and meta line | `player_hero(player, club=club)` |

All components accept canonical schema types (`Player`, `Shot`, `PercentileRow`, `RadarCategory`) and return a matplotlib `Figure`.

## Compose

Combine multiple components into a single figure:

```python
from campos import compose, player_hero, percentile_ribbon, shot_map

fig = compose(
    [player_hero(player), percentile_ribbon(stats), shot_map(shots)],
    layout="vertical",
    title="Scouting Report",
)
```

Layouts: `"vertical"`, `"horizontal"`, `"grid"`.

## Themes

```python
from campos import use_theme

use_theme("dark")   # dark background, light text (default)
use_theme("light")  # light background, dark text
```

Club accent override:

```python
import matplotlib as mpl
mpl.rcParams["campos.accent.primary"] = "#C8102E"  # Liverpool red
```

## Data schema

All coordinates normalised to 0-1 on both axes. Provider-native formats (StatsBomb 120x80, Opta 100x100) should be normalised before passing to Campos.

| Type | Required fields | Key optional fields |
|------|----------------|-------------------|
| `Player` | `id`, `name` | `position`, `nation`, `age`, `club_id` |
| `Club` | `id`, `name` | `colour_primary`, `crest_url` |
| `Shot` | `id`, `xg` | `x`, `y`, `outcome`, `body_part` |
| `PercentileRow` | `stat_id`, `label`, `value`, `percentile` | `category`, `comparison_percentile` |
| `RadarCategory` | `label`, `value`, `max` | `comparison_value`, `reversed` |

## Quality bar

Every component passes a 12-axis quality checklist before shipping. See [Testing](docs/testing.md) for details.

## Status

**v0.1.0rc1** - Release candidate. All 8 components pass the 12-axis quality bar with 272 tests. Looking for beta testers.

## Licence

MIT
