Skip to main content

Spiel des Jahres predictions

Project description

Spiel des Jahres

PyPI PyPI - Python Version PyPI - License Coookiecutter - Wolt


Documentation: https://recommend-games.github.io/spiel-des-jahres

Source Code: https://github.com/recommend-games/spiel-des-jahres

PyPI: https://pypi.org/project/spiel-des-jahres/


Generating Annual Predictions

The full prediction lifecycle involves gathering review data, exporting jury preferences to the recommendation engine, retraining the model, and finally generating rankings.

Project Structure

This project assumes a sibling directory structure for its dependencies:

  • board-game-data/: Master datasets.
  • board-game-scraper/: Scraper feeds and local .jl items.
  • board-game-merger/: Data merging tools.
  • recommend-games-server/: Recommender training and deployment.
  • spiel-des-jahres/: This repository.

Required External Datasets

  • BGG Games Dataset: ../board-game-data/scraped/bgg_GameItem.csv (Used for matching BGG IDs and game features).

1. Scrape & Update Master Reviews

Collect new reviews from the spiel-des-jahres.de Kritikenrundschau and update the master dataset.

# 1a. Run the spider (requires LLM_API_KEY)
mkdir -p results
uv run --extra scraper scrapy runspider src/spiel_des_jahres/review_spider.py

# 1b. Update master kritikenrundschau.csv
uv run python -m spiel_des_jahres.update_reviews \
    $(ls -t results/reviews-*.jl | head -n 1) \
    --bgg-games ../board-game-data/scraped/bgg_GameItem.csv

2. Prepare the Annual Data Directory

Set up the data and artefacts directories:

YEAR=$(date +%Y)
mkdir -p "src/spiel_des_jahres/data/${YEAR}"
mkdir -p artefacts
  • reviews.csv: The candidate pool for the target year. Typically manually filtered from kritikenrundschau.csv to include only eligible games for the current cycle.
  • exclude.csv: BGG IDs of games to disqualify (e.g., previous winners or ineligible reprints). One BGG ID per line under a bgg_id header.

3. Export Scraper Items (.jl)

Convert local reviews and historical awards into "scraper items" (User and Rating objects) and store them in the board-game-scraper feed directories.

# Define metadata and feed paths
TIMESTAMP=$(date -u +%Y-%m-%dT%H-%M-%S)
FEED_DIR="../board-game-scraper/feeds/bgg"

# 3a. Export Jury Member profiles (kritikenrundschau first, then per-year reviews)
uv run python -m spiel_des_jahres.ratings --item-type user \
    --kritikenrundschau-file src/spiel_des_jahres/data/kritikenrundschau.csv \
    --reviewer-prefix "s_d_j_" \
    > "${FEED_DIR}/UserItem/${TIMESTAMP}-sdj.jl"
uv run python -m spiel_des_jahres.ratings --item-type user \
    --year "${YEAR}" \
    --reviews-file "src/spiel_des_jahres/data/${YEAR}/reviews.csv" \
    --reviewer-prefix "s_d_j_" \
    >> "${FEED_DIR}/UserItem/${TIMESTAMP}-sdj.jl"

# 3b. Export Jury Member ratings (kritikenrundschau first, then per-year reviews)
# Run order matters: both use scraped_at=now, so the later run's timestamps are
# newer; the board-game-merger keeps the most recent item per (user, game) pair,
# giving the per-year reviews.csv values precedence over the historical ones.
uv run python -m spiel_des_jahres.ratings --item-type rating \
    --kritikenrundschau-file src/spiel_des_jahres/data/kritikenrundschau.csv \
    --reviewer-prefix "s_d_j_" \
    > "${FEED_DIR}/RatingItem/${TIMESTAMP}-sdj.jl"
uv run python -m spiel_des_jahres.ratings --item-type rating \
    --year "${YEAR}" \
    --reviews-file "src/spiel_des_jahres/data/${YEAR}/reviews.csv" \
    --reviewer-prefix "s_d_j_" \
    >> "${FEED_DIR}/RatingItem/${TIMESTAMP}-sdj.jl"

# 3c. Export the Jury (as a whole) historical award ratings
uv run python -m spiel_des_jahres.ratings --item-type rating \
    --awards-file src/spiel_des_jahres/data/sdj.csv \
    --awards-user "s_d_j" \
    >> "${FEED_DIR}/RatingItem/${TIMESTAMP}-sdj.jl"
uv run python -m spiel_des_jahres.ratings --item-type rating \
    --awards-file src/spiel_des_jahres/data/kindersdj.csv \
    --awards-user "s_d_j" \
    >> "${FEED_DIR}/RatingItem/${TIMESTAMP}-sdj.jl"
uv run python -m spiel_des_jahres.ratings --item-type rating \
    --awards-file src/spiel_des_jahres/data/ksdj.csv \
    --awards-user "s_d_j" \
    >> "${FEED_DIR}/RatingItem/${TIMESTAMP}-sdj.jl"

4. Retrain the Recommender Model

The exported items in the feed directories must be merged with broader BGG scrapes to update the master dataset and the recommendation engine.

  1. Merge: Update the master dataset in ../board-game-data/ by running the following command from the ../board-game-merger/ directory:

    cd ../board-game-merger/
    poetry run python -m board_game_merger all \
        --progress-bar \
        --verbose \
        --clean-results \
        --overwrite
    
  2. Process, Train & Sync: Run the prediction lifecycle tasks from the ../recommend-games-server/ directory. This updates CSVs, retrains the model, snapshots rankings, and pushes changes to the master repository:

    cd ../recommend-games-server/
    pipenv run pynt gitprepare makecsvs referencecsvs link updatecount gitupdate
    pipenv run pynt "trainbgg[out_path_light=$(pwd)/../spiel-des-jahres/artefacts/recommender_light.npz]"
    
    • gitprepare: Ensures the data repository is clean and up-to-date.
    • makecsvs / referencecsvs: Updates CSV versions of the master data and foreign references.
    • link: Updates game linkages (links.json).
    • updatecount: Updates the line and file counts in COUNT.md.
    • gitupdate: Commits and pushes the updated data to the master repository.
    • trainbgg: Retrains the recommender model and exports the light artefact.

5. Train the Kennerspiel Model

Train the local classifier that identifies "Kennerspiel" candidates.

uv run python -m spiel_des_jahres.kennerspiel artefacts/kennerspiel.joblib

6. Generate Final Rankings

With the data prepared and the models updated, generate the final rankings.

uv run python -m spiel_des_jahres.predictions \
    --year "${YEAR}" \
    --recommender-model artefacts/recommender_light.npz \
    --kennerspiel-model artefacts/kennerspiel.joblib \
    --output "src/spiel_des_jahres/data/${YEAR}/predictions.csv"

Installation

pip install spiel-des-jahres

Development

  • Clone this repository
  • Requirements:
    • uv
    • Python 3.10+
  • Create a virtual environment and install the dependencies
uv sync --all-extras

Testing

uv run pytest

Documentation

The documentation is automatically generated from the content of the docs directory and from the docstrings of the public signatures of the source code. The documentation is updated and published as a Github Pages page automatically as part each release.

Releasing

Trigger the Draft release workflow (press Run workflow). This will update the changelog & version and create a GitHub release which is in Draft state.

Find the draft release from the GitHub releases and publish it. When a release is published, it'll trigger release workflow which creates PyPI release and deploys updated documentation.

Pre-commit

Pre-commit hooks run all the auto-formatting (ruff format), linters (e.g. ruff and mypy), and other quality checks to make sure the changeset is in good shape before a commit/push happens.

You can install the hooks with (runs for each commit):

pre-commit install

Or if you want them to run only for each push:

pre-commit install -t pre-push

Or if you want e.g. want to run all checks manually for all files:

pre-commit run --all-files

This project was generated using the wolt-python-package-cookiecutter template.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spiel_des_jahres-0.6.0.tar.gz (300.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spiel_des_jahres-0.6.0-py3-none-any.whl (53.8 kB view details)

Uploaded Python 3

File details

Details for the file spiel_des_jahres-0.6.0.tar.gz.

File metadata

  • Download URL: spiel_des_jahres-0.6.0.tar.gz
  • Upload date:
  • Size: 300.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for spiel_des_jahres-0.6.0.tar.gz
Algorithm Hash digest
SHA256 45cef0e947c743724af779e85ff9b6b835078b0cd55060c10f66a953429158a6
MD5 adf21809b70459fddb2527a213e64faa
BLAKE2b-256 1a4d6b1ef6bd169a401d8db650a4dca73b5f5ac4162bba577b414647d048e762

See more details on using hashes here.

File details

Details for the file spiel_des_jahres-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: spiel_des_jahres-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 53.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.15 {"installer":{"name":"uv","version":"0.11.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for spiel_des_jahres-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d7698f99028279a50f36f00191e33ef72701e828d94b5fbf7ab3e9728cda18a7
MD5 aa61289f8bc6fc2e2f955bdaddaf4620
BLAKE2b-256 8b925183247d2d49efd7448796ca9369a9eb0f28bf10d87232d544e63934265d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page