Metadata-Version: 2.4
Name: localarena
Version: 0.1.0
Summary: A small, deterministic Elo arena for local model comparisons
Project-URL: Homepage, https://github.com/maziyarpanahi/localarena
Project-URL: Repository, https://github.com/maziyarpanahi/localarena
Project-URL: Issues, https://github.com/maziyarpanahi/localarena/issues
Author: Maziyar Panahi
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: arena,elo,evaluation,leaderboard,local-models
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
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: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# localarena

`localarena` is a zero-dependency Elo arena for deterministic, local
head-to-head comparisons. It keeps contestant metadata, match history, and
ratings together in a portable versioned snapshot.

```bash
pip install localarena
```

```python
from localarena import Arena, Result

arena = Arena(
    {
        "model-a": {"provider": "local"},
        "model-b": {"provider": "local"},
    }
)

arena.record("model-a", "model-b", Result.LEFT, {"prompt_id": "demo-1"})

for row in arena.standings():
    print(row.rank, row.name, row.rating)

pair = arena.next_pair()
payload = arena.to_json()
restored = Arena.from_json(payload)
```

## API

- `Arena(contestants, initial_rating=1000, k_factor=32)` accepts an iterable
  of unique names or a mapping of names to metadata.
- `add(name, metadata=None)` registers another contestant.
- `record(left, right, result, metadata=None)` records a match and applies an
  Elo update. Results are `"left"`, `"right"`, or `"draw"`.
- `standings()` and its alias `leaderboard()` return immutable rows ordered by
  rating descending, then name.
- `next_pair()` chooses the least-played unordered pair deterministically.
- `matches` and `history()` expose immutable match records.
- `snapshot()` / `to_json()` produce schema-v1 data with contestants sorted by
  name;
  `from_snapshot()` / `from_json()` validate and replay that history.
- `expected_score()` and `round_robin()` are available as standalone helpers.

Metadata must be a JSON object. Nested dictionaries, lists, tuples, strings,
booleans, `None`, finite numbers, and interoperable safe integers are
accepted. Public records recursively freeze metadata; snapshots return
detached ordinary dictionaries and lists.

The npm package uses the same result values and schema-v1 snapshot format, so
match histories can move between Python and JavaScript.
