Metadata-Version: 2.5
Name: statline
Version: 4.0.0rc6
Summary: StatLine — weighted player scoring, efficiency modeling, CLI + adapter tooling
Project-URL: Homepage, https://statline.dev
Project-URL: Repository, https://github.com/amillolive/StatLine
Project-URL: Issues, https://github.com/amillolive/StatLine/issues
Project-URL: Legal, https://github.com/amillolive/StatLine/tree/main/legal
Author: StatLine LLC
License: # StatLine – Weighted Player Scoring and Analytics
        
        Copyright (C) 2026 StatLine LLC (in formation)
        
        This program is free software: you can redistribute it and/or modify
        it under the terms of the GNU Affero General Public License as published
        by the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
        
        As an additional condition, you may not use the name “StatLine” or any
        confusingly similar mark in connection with your distribution, hosting,
        or marketing of this software without express written permission from
        the copyright holder. This restriction is to protect the StatLine brand
        and avoid confusion between official and unofficial versions.
        
        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        GNU Affero General Public License for more details.
        
        You should have received a copy of the GNU Affero General Public License
        along with this program.  If not, see <https://www.gnu.org/licenses/>.
        
        ---
        
        Additional Terms (Trademark)
        
        "StatLine" and associated logos are trademarks of StatLine LLC (in formation), trademark registration pending.  
        This license does not grant you any rights to use the StatLine name or branding without prior written permission, except for fair use when referring to the project. Any fork, derivative work, or public deployment must remove the StatLine trademark unless explicitly authorized under our Trademark Policy.
License-File: LICENSE
Keywords: adapters,analytics,basketball,cli,efg,esports,mvp,pri,slapi,statline
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Requires-Python: <3.15,>=3.10
Requires-Dist: pyyaml<7.0,>=6.0
Requires-Dist: rich<15.0,>=13.0
Requires-Dist: tomli<3.0,>=2.0.1; python_version < '3.11'
Requires-Dist: typing-extensions>=4.7; python_version < '3.15'
Provides-Extra: all
Requires-Dist: click<9.0,>=8.1; extra == 'all'
Requires-Dist: cryptography<47.0,>=42.0; extra == 'all'
Requires-Dist: fastapi<1.0,>=0.110; extra == 'all'
Requires-Dist: httpx2<3.0,>=2.0; extra == 'all'
Requires-Dist: pydantic<3.0,>=2.6; extra == 'all'
Requires-Dist: textual<9.0,>=8.0; extra == 'all'
Requires-Dist: typer<1.0,>=0.12; extra == 'all'
Requires-Dist: uvicorn[standard]<1.0,>=0.30; extra == 'all'
Provides-Extra: app
Requires-Dist: click<9.0,>=8.1; extra == 'app'
Requires-Dist: httpx2<3.0,>=2.0; extra == 'app'
Requires-Dist: textual<9.0,>=8.0; extra == 'app'
Requires-Dist: typer<1.0,>=0.12; extra == 'app'
Provides-Extra: dev
Requires-Dist: build<2.0,>=1.2; extra == 'dev'
Requires-Dist: click<9.0,>=8.1; extra == 'dev'
Requires-Dist: coverage[toml]<8.0,>=7.5; extra == 'dev'
Requires-Dist: cryptography<47.0,>=42.0; extra == 'dev'
Requires-Dist: fastapi<1.0,>=0.110; extra == 'dev'
Requires-Dist: httpx2<3.0,>=2.0; extra == 'dev'
Requires-Dist: hypothesis<7.0,>=6.100; extra == 'dev'
Requires-Dist: mkdocs-material<10.0,>=9.5; extra == 'dev'
Requires-Dist: mkdocstrings[python]<1.0,>=0.25; extra == 'dev'
Requires-Dist: mypy<2.0,>=1.11; extra == 'dev'
Requires-Dist: pip-audit<3.0,>=2.7; extra == 'dev'
Requires-Dist: pydantic<3.0,>=2.6; extra == 'dev'
Requires-Dist: pyright<2.0,>=1.1.370; extra == 'dev'
Requires-Dist: pytest-cov<7.0,>=4.1; extra == 'dev'
Requires-Dist: pytest>=8.1; extra == 'dev'
Requires-Dist: ruff<1.0,>=0.5; extra == 'dev'
Requires-Dist: textual<9.0,>=8.0; extra == 'dev'
Requires-Dist: twine<8.0,>=7.0; extra == 'dev'
Requires-Dist: typer<1.0,>=0.12; extra == 'dev'
Requires-Dist: types-pyyaml>=6.0.12; extra == 'dev'
Requires-Dist: types-requests>=2.32; extra == 'dev'
Requires-Dist: uvicorn[standard]<1.0,>=0.30; extra == 'dev'
Provides-Extra: gateway
Requires-Dist: cryptography<47.0,>=42.0; extra == 'gateway'
Requires-Dist: fastapi<1.0,>=0.110; extra == 'gateway'
Requires-Dist: pydantic<3.0,>=2.6; extra == 'gateway'
Requires-Dist: uvicorn[standard]<1.0,>=0.30; extra == 'gateway'
Description-Content-Type: text/markdown

# StatLine

**StatLine** is an adapter-driven scoring and analytics toolkit for turning raw stat rows into weighted, explainable ratings.

It can run completely locally for simple scoring workflows, or against **SLAPI**, the optional StatLine API layer for authenticated remote scoring, adapter inspection, and multi-client deployments.

> **Release target:** **v4.0.0rc6** — preview on [`next`](https://github.com/amillolive/StatLine/tree/next).
> **Stable line:** v3 on [`main`](https://github.com/amillolive/StatLine/tree/main). The APIs and examples in this checkout describe v4, not v3.
> **Python:** **3.10 through 3.14**
> **License:** **AGPL-3.0-or-later**, with separate trademark restrictions for the StatLine name and branding.

---

## What StatLine does

StatLine takes raw rows such as CSV box-score data, maps those rows through an adapter, scores the mapped metrics, then returns profile scores such as **PRI** and adapter-defined variants.

At a high level, StatLine provides:

* **Adapter-based scoring** for different games, leagues, datasets, or stat schemas.
* **Local scoring** through the Python package and `statline` CLI.
* **Remote/API scoring** through SLAPI when installed with the remote stack.
* **Weighted score profiles**, including PRI-style outputs and adapter-defined variants.
* **Batch scoring**, row scoring, mapping-only commands, and already-mapped calculation commands.
* **Adapter inspection tools** for inputs, metrics, dimensions, filters, weights, and sniffing.
* **Typed public Python API** for bots, dashboards, notebooks, and application code.

---

## v4.0.0rc6 highlights

* The Gateway supports opt-in `response_format="compact"`, moving equal context, weights and explanation configuration into `shared` without changing scored values. Legacy remains the default.
* Results preserve original `source_index` and an adapter identity `source_id` (PLAYER or TEAM for EBA), including through raw and mapped filtering.
* Optional `output.show_explanation` traces actual normalized metrics, effective profile weights, raw contributions, midpoint-relative influences, transforms, limits and rounding. The portal uses these engine-produced explanations.
* Public pages use saved data until you choose an API check. Browser integration registration has been removed, and the API root provides helpful HTML for browser navigation while retaining JSON for machine clients.
* Root `launch.ps1` / `launch.sh` start the API and built portal together, configure exact local CORS origins, and verify health, OpenAPI and authenticated-request preflights.
* Release archives and distributions are scanned for private runtime artifacts; generated contracts include source fingerprints and generation timestamps.

* Core, App, and Gateway are ordinary directories in the canonical StatLine monorepo; their standalone repositories are generated with `git subtree split` while preserving `statline.core`, `statline.app`, and `statline.gateway` import paths.
* Core now has an enforced no-App/no-Gateway import boundary; the canonical extras are `app`, `gateway`, `all`, and `dev`, with App and Gateway independently installable above Core.
* Root CLI help is organized around core workflows, service/access, administration, and one advanced `tools` namespace; rc3 command spellings remain hidden compatibility aliases.
* Connectivity output now distinguishes **SLAPI unavailable** from **SLAPI reachable but unauthenticated**, and `serve` does not preflight/report unrelated client connectivity.
* StatLine OS executes the canonical CLI command tree in-process, so command names/help/validation match the regular CLI and copied `statline ...` commands can be pasted directly.
* The Windows installer builder now keeps Inno Setup candidates as an explicit array under PowerShell StrictMode, fixing the one-candidate `.Count` failure.
* Compiled adapters now execute against a trusted numeric context, avoiding repeated numeric coercion in expression hot paths.
* Dataset aggregate expressions declare their required operations at compile time, so batches only prepare the headers and aggregates an adapter actually uses.
* Scoring can opt into selected profiles with `profiles=[...]`; existing callers still receive every adapter-defined profile by default.
* Output-aware scoring skips disabled bucket, component, weight, and context payload construction instead of allocating data only to discard it later.
* CLI score output uses the lean scoring path when `--details` is not requested while preserving the existing displayed/exported fields.
* `statline os` now mirrors the canonical CLI command tree in-process, accepts pasted `statline ...` commands directly, and keeps persistent OS session state.
* SLAPI scoring is kept off the async event loop and the server runner can use multiple worker processes through `SLAPI_WORKERS`.
* Deprecated adapter schemas are no longer discoverable through CLI/API lists or sniffing; an explicit local YAML path is required to use one.

---

## Install

This archive is a patched rc6 checkout. Use `python -m pip install -e ".[all]"` from this checkout to run these changes. Pinning an existing PyPI rc6 package does not apply local source edits. Read [RC6_CHANGES.md](RC6_CHANGES.md) for the compact response migration and [RC6_VERIFICATION.md](RC6_VERIFICATION.md) for completed checks.

StatLine v4.0.0rc6 has five intended install variants. The StatLine repository is the canonical development and release-composition monorepo; standalone Core, App, and Gateway repositories are generated mirrors of their corresponding paths.

| Variant | Command | Capability set |
| --- | --- | --- |
| **core** | `pip install "statline==4.0.0rc6"` | Core Python API, scoring, adapters, datasets, and StatPack runtime. |
| **app** | `pip install "statline[app]==4.0.0rc6"` | Core + CLI/application dependencies + Textual StatLine OS. |
| **gateway** | `pip install "statline[gateway]==4.0.0rc6"` | Core + authentication, API, and SLAPI serving dependencies. |
| **all** | `pip install "statline[all]==4.0.0rc6"` | Core + App + Gateway runtime capabilities. |
| **dev** | `pip install -e ".[dev]"` | Core + App + Gateway plus tests, typing, docs, packaging, and release tooling. |

For a source checkout, clone the monorepo normally:

```bash
git clone --branch next https://github.com/amillolive/StatLine.git
cd StatLine
python -m venv .venv

# Linux/macOS
source .venv/bin/activate

# Windows PowerShell
# .\.venv\Scripts\Activate.ps1

python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```

Core is intentionally one-way: `statline/core` must never import App or Gateway. App and Gateway may consume Core; cross-capability App/Gateway integration must remain behind the capability that supplies its dependencies.

---

## Quick start: local CLI

The CLI is part of the App capability; install `statline[app]`, `statline[all]`, or `statline[dev]` before using these commands.

Local mode avoids all network probing and uses the installed StatLine core directly.

```bash id="y41591"
statline --mode local adapter list
statline --mode local adapter inputs eba.players
statline --mode local adapter weights eba.players
```

Score a bundled EBA CSV from a source checkout:

```bash id="o3hhff"
statline --mode local score \
  --adapter eba.players \
  EBA_Elevate302/eba_s1_players.csv \
  --fmt table \
  --profile all \
  --percentile \
  --limit 10
```

Write JSON instead:

```bash id="y19azp"
statline --mode local score \
  --adapter eba.players \
  EBA_Elevate302/eba_s1_players.csv \
  --fmt json \
  --pretty \
  --out results.json
```

> On Windows PowerShell, either enter the command on one line or use PowerShell's backtick continuation character instead of `\`.

---

## Quick start: Python API

```python id="2eosv5"
from statline import list_adapters, load_dataset, score

print(list_adapters())

rows = load_dataset("EBA_Elevate302/eba_s1_players", limit=10)

results = score(
    "eba.players",
    rows,
    mode="batch",
    weights="pri",
)

for row in results[:3]:
    print(row["pri"], row["pri_raw"], row.get("scores", {}))
```

For one row:

```python id="9pi6fe"
from statline import score_row

player = {
    "PLAYER": "Example Player",
    "GP": 12,
    "PPG": 24.5,
    "RPG": 5.0,
    "APG": 6.2,
    "SPG": 1.5,
    "BPG": 0.7,
    "TPG": 2.1,
    "FGMPG": 9.2,
    "FGAPG": 18.4,
    "WIN": 9,
    "LOSS": 3,
}

result = score_row("eba.players", player, weights="pri")

print(result["pri"])
```

---

## CLI overview

The main command is:

```bash id="6cucra"
statline --help
```

Useful global options:

| Option                   | Meaning                                                                                    |
| ------------------------ | ------------------------------------------------------------------------------------------ |
| `--mode auto`            | Probe SLAPI; use remote when reachable and authenticated, otherwise local where supported. |
| `--mode local`           | Force local StatLine core execution and skip SLAPI entirely.                               |
| `--mode remote`          | Require SLAPI to be reachable and authenticated.                                           |
| `--url URL`              | Set the SLAPI base URL. Also supported through `SLAPI_URL`.                                |
| `--timing / --no-timing` | Show or hide timing summaries.                                                             |
| `--version`              | Print the CLI version.                                                                     |

Primary user commands:

| Command                                     | Purpose                                         |
| ------------------------------------------- | ----------------------------------------------- |
| `statline adapter list`                     | List adapters.                                  |
| `statline adapter spec <adapter>`           | Show adapter metadata/spec details.             |
| `statline adapter inputs <adapter>`         | Show raw input keys expected by an adapter.     |
| `statline adapter metrics <adapter>`        | Show mapped metric keys.                        |
| `statline adapter weights <adapter>`        | Show available weight profiles.                 |
| `statline adapter filters <adapter>`        | Show adapter-declared filters.                  |
| `statline adapter sniff --file stats.csv`   | Detect matching adapters from headers.          |
| `statline os`                               | Launch StatLine OS in a separate Windows window.|
| `statline os --inline`                      | Run StatLine OS in the current terminal.        |
| `statline score`                            | Map and score raw CSV/YAML/JSON rows.           |
| `statline tools map row` / `... map batch`  | Advanced mapping-only pipeline stage.           |
| `statline tools calc row` / `... calc batch`| Advanced scoring of already-mapped metrics.     |
| `statline tools ...`                        | Cache, CSV/storage, map/calc, and weight tools. |
| `statline statpack run <pack>`              | Run a trusted StatPack.                         |
| `statline serve`                            | Start SLAPI locally. Requires the remote stack. |
| `statline auth ...`                         | Device enrollment and API key workflows.        |
| `statline system status`                    | Runtime, backend, auth, paths, and logs.        |

---

## Scoring concepts

### Adapter

An adapter is a YAML contract that explains how to turn raw fields into StatLine metrics. It defines:

* metadata such as `key`, `version`, `aliases`, and `title`,
* raw-to-metric mappings,
* derived efficiency metrics,
* buckets,
* weight profiles,
* penalties,
* score profiles,
* optional dimensions and filters,
* optional sniffing rules for adapter detection.

### Metric

A metric is a numeric signal used by the scoring engine. Metrics can be direct fields, constants, or safe expressions over previous values.

### Bucket

A bucket groups metrics for weighting. A PRI profile does not usually weight every metric one by one; it weights the buckets.

### Weight profile

A weight profile defines how strongly each bucket contributes. The default profile is usually `pri`, but adapters can expose more.

### Score profile

A score profile controls how the normalized raw score becomes a published score. StatLine supports affine profiles and windowed profiles.

### PRI and `pri_raw`

`pri_raw` is the normalized raw score. `pri` is the adapter/profile-rendered score.

Some adapters also expose additional profile scores such as `pri_af`, `pri_ar`, or `pri_ap`.

---

## Dataset-relative expressions

Adapters can reference aggregate values from the current input dataset when mapping rows.

Available dataset aggregate functions include:

```text id="ub6957"
dataset_max("FIELD")
dataset_min("FIELD")
dataset_mean("FIELD")
dataset_median("FIELD")
dataset_sum("FIELD")
dataset_count("FIELD")
```

Field lookup is case-insensitive.

This allows adapters to define scoring behavior relative to the current dataset rather than relying exclusively on fixed constants. For example:

```yaml id="4cujrf"
rel_gp:
  expr: min(1.0, real_gp / max(1.0, dataset_max("GP") * 0.65))
```

In batch workflows, dataset aggregates are calculated once for the input dataset and shared while mapping its rows.

---

## Input formats

The CLI reads CSV, YAML, JSON-like YAML, and stdin CSV for commands that accept file input.

CSV example:

```csv id="gvkm74"
name,ppg,apg,orpg,drpg,spg,bpg,tov,fgm,fga,win,loss
Example Player,24.5,6.2,1.0,4.0,1.5,0.7,2.1,9.2,18.4,12,8
```

YAML example:

```yaml id="fxaqlq"
- name: Example Player
  ppg: 24.5
  apg: 6.2
  orpg: 1.0
  drpg: 4.0
  spg: 1.5
  bpg: 0.7
  tov: 2.1
  fgm: 9.2
  fga: 18.4
  win: 12
  loss: 8
```

---

## Remote/API mode

Install the Gateway capability:

```bash id="wgthnb"
pip install "statline[gateway]"
```

Start SLAPI directly:

```bash id="s5jyot"
SLAPI_HOST=127.0.0.1 SLAPI_PORT=8000 slapi
```

If you want to control the server through the `statline` CLI instead, install both runtime capabilities:

```bash
pip install "statline[all]"
statline --mode local serve --host 127.0.0.1 --port 8000
```

Then point clients at it:

```bash id="702qy0"
export SLAPI_URL="http://127.0.0.1:8000"
statline --mode remote system status
```

On Windows PowerShell:

```powershell id="gvswq9"
$env:SLAPI_URL = "http://127.0.0.1:8000"
statline --mode remote system status
```

SLAPI supports protected authentication flows. Normal remote use requires both device enrollment and an API key. Administrative and moderation commands require the corresponding scopes.

Common auth flow:

```bash id="uh101l"
statline auth device-init
statline auth enroll --token reg_... --user your-handle --email you@example.com
statline auth apikey-request --owner your-name
statline auth apikey-claim --request-id REQUEST_ID
statline auth whoami
```

The exact approval steps depend on the SLAPI administrator.

---

## Development

Install the development pack:

```bash id="yqoh3s"
python -m pip install -e ".[dev]"
```

Run checks:

```bash id="pguk4i"
pytest
ruff check statline tests
mypy statline
pyright
```

Build release artifacts:

```bash id="3eg9vw"
python -m build
twine check dist/*
```

---

## Legal

StatLine source code is licensed under the **GNU Affero General Public License v3 or later**. The StatLine name, marks, and logos are not granted by the source license.

See:

* `LICENSE`
* `TRADEMARK_POLICY.md`
* `CLA.md`
* `legal/tos.md`
* `legal/privacypolicy.md`
* `legal/aup.md`

---

## Repository

* Homepage: <https://statline.dev>
* Repository: <https://github.com/amillolive/StatLine>
* Issues: <https://github.com/amillolive/StatLine/issues>
* API Documentation: <https://api.statline.dev/redoc>
* Interactive API Documentation: <https://api.statline.dev/docs>
