This guide provides instructions for running the processor locally to generate player ratings from publicly-available datasets. This enables independent verification of tournaments which use our platform for filtering and/or seeding.
Important
The
otr-processorversion must be the most recent version released before the tournament’s registration period. The processor uses date-based versioning inYYYY.MM.DDformat. Different processor versions may produce different results due to algorithm updates.
Prerequisites
- Docker
- (Windows only) Git Bash or WSL - required because these commands use Unix-style syntax not supported by Windows Command Prompt or PowerShell.
- Follow the setup instructions in the development guide so you have the
otr-webandotr-processorrepositories available locally.
Step 1: Start the database
Start Postgres and RabbitMQ from the otr-web repository directory:
# From the `otr-web` repository
docker compose up -d db rabbitmqStep 2: Import database replica
Public database replicas are published on the public replicas site. These weekly replicas exclude most data, but provide enough data to verify a tournament’s use of o!TR.
Download the most recent replica dated before the tournament closed registrations. If the tournament provides another date by which ratings are taken from, use that date instead.
Verify the download (optional)
As of November 26, 2025, each replica is accompanied by a .sha256 checksum file and a .sig GPG signature file. These allow you to verify that the data hasn’t been tampered with.
SHA-256 verification (integrity only):
Download the .sha256 file for your replica and run:
sha256sum -c otr-public-replica_YYYY_MM_DD_HH_MM_SS.gz.sha256GPG signature verification (integrity + origin):
Download the public key (one-time) and the .sig file for your replica:
curl -O https://storage.googleapis.com/otr-public-replica/otr-public-key.asc
gpg --import otr-public-key.asc
gpg --verify otr-public-replica_YYYY_MM_DD_HH_MM_SS.gz.sig otr-public-replica_YYYY_MM_DD_HH_MM_SS.gzIf verification succeeds, the output will contain Good signature from "o!TR Public Data Signing Key". You may also see a warning about the key not being certified with a trusted signature—this is expected and can be ignored.
Import the replica
gunzip -c /path/to/replica.gz | docker exec -i db bash -c "psql -U postgres -d template1 -c 'DROP DATABASE IF EXISTS postgres;' && psql -U postgres -d template1 -c 'CREATE DATABASE postgres;' && psql -U postgres -d postgres"Tip
Some errors, such as
ERROR: role [...] does not exist, can be safely ignored.
Step 3: Run the processor
Browse the releases page to find a processor version to use. Then, take the name of the release and replace the YYYY.MM.DD text below with that value.
Note
The processor publishes queue messages to generate stats for processed tournaments. Its management console lives at
http://localhost:15672/. UnderQueues and Streams, you can see the status of all queues.
docker run --rm \
--name otr-processor \
--network host \
-e CONNECTION_STRING="postgresql://postgres:password@localhost:5432/postgres" \
-e IGNORE_CONSTRAINTS=true \
stagecodes/otr-processor:YYYY.MM.DDTip
Replace
YYYY.MM.DDwith the processor release version.
Tip
To run pre-production changes, use the
:stagingtag. To run the latest production version, use the:latesttag.Example:
docker run ... stagecodes/otr-processor:staging
Step 4: Export player ratings
Export player ratings for verification. Replace ruleset values as follows:
- 0=osu!
- 1=osu!taiko
- 2=osu!catch
- 3=osu!mania (Other) [No ratings are generated for this ruleset]
- 4=osu!mania 4K
- 5=osu!mania 7K
Export specific game mode (recommended)
# Export osu! ratings (ruleset = 0)
docker exec -it db psql -U postgres -d postgres -c "\
COPY (
SELECT
p.osu_id,
p.username,
p.country,
pr.rating,
pr.global_rank,
pr.country_rank
FROM public.players p
JOIN public.player_ratings pr ON p.id = pr.player_id
WHERE pr.ruleset = 0
-- ^^^ == Edit ruleset here ==
ORDER BY pr.rating DESC
) TO STDOUT WITH CSV HEADER;" > ratings.csvExport all ratings
Note
One player may have multiple ratings, one per ruleset.
# Export all player ratings to CSV
docker exec -it db psql -U postgres -d postgres -c "\
COPY (
SELECT
p.osu_id,
p.username,
p.country,
pr.ruleset,
pr.rating,
pr.volatility,
pr.percentile,
pr.global_rank,
pr.country_rank
FROM public.players p
JOIN public.player_ratings pr ON p.id = pr.player_id
ORDER BY pr.ruleset, pr.rating DESC
) TO STDOUT WITH CSV HEADER;" > ratings.csvCleanup
Remove the created containers and volumes (to keep the database and other volumes, remove -v).
docker compose down -vTroubleshooting
- Database connection refused: Ensure PostgreSQL container is running with
docker ps - Processor runs but crashes: Ensure the
IGNORE_CONSTRAINTS=trueenvironment variable is set (using-e). If other unexpected issues occur, please contact us. - Export produces empty files: Verify the database import completed successfully