尚未检测到更新。GitHub 发布版本后会显示在这里。
制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗Local FPL engine. No web app — everything runs from the CLI and outputs to terminal + JSON. The differentiator is mini-league intelligence: it optimises against your rivals, not just for raw points.
| Module | What it does |
|---|---|
src/rivalr/fetch.py | FPL API client, disk cache (6h bootstrap, 1h standings), 429 backoff, cache-miss logging |
src/rivalr/rivals.py | rival squads, chips, banks, transfer history; mini-league effective ownership; SHIELD/SWORD/NEUTRAL classification; per-rival overlap and differentials → rivals_report.json |
src/rivalr/model.py | OpenFPL trained-model inference (no retraining), 228 rolling-window features from FPL + Understat |
src/rivalr/understat.py | Understat JSON API client (league + player endpoints), cross-season history, loud failure logging |
src/rivalr/minutes.py | v0 expected-minutes: rolling starts, minutes trend, availability flag, congestion; news-based v1 hook |
src/rivalr/optimise.py | wraps the FPL-Optimization-Tools HiGHS MILP with our projections; three objectives: points / chase / defend |
src/rivalr/report.py | one-command gameweek brief (Telegram-friendly plain text) |
src/rivalr/ledger.py + score.py | append-only prediction ledger, post-GW RMSE/MAE by outcome bucket + transfer counterfactual |
Requires uv and git.
uv sync
uv run python scripts/setup_vendors.py # clones OpenFPL (~750MB models) + FPL-Optimization-Tools into vendor/
The gameweek brief (the main command):
uv run python -m rivalr.report --team <your_entry_id> --league <classic_league_id> --mode chase --target <rival_entry_id>
--mode points — plain xPts maximisation (no target needed)--mode chase --target <id> — attack a rival above you: differentials + variance--mode defend --target <id> — protect a lead: cover the chaser's squad, prefer shieldsAll three plans are always solved and shown side by side with honest (unweighted) expected points and a next-GW swing-vs-target estimate.
Score a finished gameweek against the ledger:
uv run python -m rivalr.score --gw 5
Smoke tests (no team/league needed):
uv run python scripts/smoke.py # fetch + model + minutes
uv run python scripts/smoke_optimise.py # full MILP solve
Tests:
uv run pytest
OpenFPL (vendor/OpenFPL, daniegr/OpenFPL): 250 joblib models
(xgboost 3.0.2 / sklearn 1.5.2-era pickles; deps pinned in our
pyproject to their plug.txt). Input is a 228-feature vector per
(player, fixture): rolling means of FPL + Understat stats over the
previous {1,3,5,10,38} gameweeks, min-max scaled by models/xscaler.save,
sliced per position via models/features.save, predicted by 50 models
per position (5 CV folds x 10 candidates), inverse-scaled
(points = y*33 - 7), median-ensembled. Predicts one GW at a time; we
re-run per future fixture with the opponent block swapped.
FPL-Optimization-Tools (vendor/FPL-Optimization-Tools,
sertalpbilal): HiGHS MILP via highspy. We bypass its CLI and call
dev.solver.prep_data + solve_multi_period_fpl directly, writing our
projections into vendor/.../data/rivalr_<mode>.csv in its fplreview
format: ID,Name,Pos,Value,Team,{gw}_Pts,{gw}_xMins,... (ID = FPL
element id; Pos in G/D/M/F; the solver re-derives prices/teams from
bootstrap-static). Options come from its comprehensive_settings.json
plus our overrides (see SOLVER_OVERRIDES in optimise.py).
uv sync --extra api
uv run uvicorn rivalr.api:app --port 8000
GET /health — status, gameweek, deadline, last snapshot timeGET /brief?team_id&league_id&mode&target — the brief as JSON
(squad with base/defcon/flags, captain, transfers with per-rival
swings, rivals block, warnings). Slow solves return {job_id} (202);
poll GET /brief/status?job_id=.GET /league?league_id — standings + entry ids for a target picker.Caching: Postgres via DATABASE_URL (in-memory fallback without it),
keyed (team, league, mode, target, gw), TTL 1h, always bypassed inside
the 4h pre-deadline window. Rate limit 30 req/min/IP. CORS allows
localhost dev ports plus RIVALR_CORS_ORIGINS (comma-separated).
Run a SINGLE uvicorn worker process — jobs and cache-bypass state are
in-process.
A rivals failure degrades to rivals: null plus a warning; squad and
transfers still return.
The Dockerfile serves both processes: web (default CMD, uvicorn) and
worker (python -m rivalr.worker — the same hourly snapshot code path
as the local Task Scheduler entry). Model artifacts (~750MB of OpenFPL
joblibs) are NOT in the image: the entrypoint clones both vendor repos
into RIVALR_VENDOR_DIR on first boot — mount a Railway volume at
/data per service so it happens once. Env per service:
RIVALR_TEAM_ID, RIVALR_LEAGUE_ID, RIVALR_TELEGRAM_BOT_TOKEN,
RIVALR_TELEGRAM_CHAT_ID, RIVALR_CORS_ORIGINS (web),
DATABASE_URL (web; from the Railway Postgres plugin). Once the
Railway worker is verified, disable the local Task Scheduler entry
(schtasks /Change /TN rivalr-snapshot /DISABLE) so one snapshot
source is canonical.
以上为 README 的开头部分。其余内容请阅读原文。 查看完整 README ↗