# archon
Tournament management
## Development install
This project uses [npm](https://docs.npmjs.com), that you can install with [nvm](https://github.com/nvm-sh/nvm).
It also uses [Python](https://docs.python.org/3/) on the backend side, so install Python version >= `3.11`.
Finally, you'll need [GNU Make](https://www.gnu.org/software/make/manual/make.html) for simple targets and processes defined in a [Makefile](Makefile).
Four options if you are on Windows:
- Use [Chocolatey](https://chocolatey.org) as package manager and `choco install make`
- Use the [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/) feature
- Just install the [GNU make binary for Windows](https://gnuwin32.sourceforge.net/packages/make.htm)
- Don't use `make` at all. The [Makefile](Makefile) is just a shortcut, you can open it and copy/paste the commands in your Powershell.
```bash
nvm install node
nvm use node
python -m virtualenv .venv
source .venv/bin/activate
make update
```
We are using a couple of very standard tools and frameworks, that `make update` will install and update for you:
- [Typescript](https://www.typescriptlang.org/docs/) our frontend language
- [Bootstrap](https://getbootstrap.com/docs) and its [icons](https://icons.getbootstrap.com), for basic styling & responsiveness
- [Parcel](https://parceljs.org/docs/) as our build framework for frontend
- [FastAPI](https://fastapi.tiangolo.com/learn/) as our backend server framework,
with [Jinja2](https://jinja.palletsprojects.com/en/stable/) for HTML templating,
its [i18n extension](https://jinja.palletsprojects.com/en/stable/extensions/#i18n-extension) for potential future translations,
and [pyJWT](https://pyjwt.readthedocs.io/en/stable/) for generating [OAuth 2.0](https://oauth.net/2/) [JWT (RFC 7519)](https://datatracker.ietf.org/doc/html/rfc7519) tokens.
- [PostgreSQL](https://www.postgresql.org/docs/current/index.html) for database,
with [psycopg3](https://www.psycopg.org/psycopg3/docs/) as our library to instrument it
- [AIOHTTP](https://docs.aiohttp.org) for web queries
- [Black](https://black.readthedocs.io/en/stable/) and [Ruff](https://docs.astral.sh/ruff/) for python formatting and linting, respectively
- [Twine](https://twine.readthedocs.io/en/stable/) to publish our Python package to the public [PYPI](https://pypi.org) repository.
- [PM2](https://pm2.keymetrics.io/docs/usage/quick-start/) to run our hot reload development services (front & back)
- [Geonames](https://www.geonames.org) for countries and cities names and IDs
- [Typer](https://typer.tiangolo.com) for the [`archon` Command-Line Interface (CLI)](#cli)
## Make targets
- `make geodata` downlad and refresh the geographical data in [geodata](src/archon/geodata)
- `make test` runs the tests, formatting and linting checks
- `make serve` runs a dev server with watchers for auto-reload when changes are made to the source files
- `make clean` cleans the repository from all transient build files
- `make build` builds the python package
- `make release` creates and pushes a git tag for this version and publishes the package on [PYPI](https://pypi.org)
## CLI
The `archon` CLI gives access to useful DB-related commands when developing in local.
```bash
> archon --help
Usage: archon [OPTIONS] COMMAND [ARGS]...
╭─ Options ───────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --install-completion Install completion for the current shell. │
│ --show-completion Show completion for the current shell, to copy it or customize the installation. │
│ --help Show this message and exit. │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ──────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ list │
│ purge │
│ reset-db │
│ sync-members │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
```
## Development database
You need a running [PostgreSQL](https://www.postgresql.org/docs/current/index.html) server, with an `archon` superuser,
an `archondb` database owned by that superuser, with no password.
You can use the `DB_USER` and `DB_PWD` environment variables to use other values. The database name is not configurable.
## Development server
Use `openssl` to generate a secure token secret for signing our [JWT]() access tokens.
```bash
openssl rand -hex 32
```
Set this value for the `TOKEN_SECRET` environment variable, for example in a `.env` file at the repository's root.
```bash
export TOKEN_SECRET="[The generated secret string]"
```
Simply use `make serve` to run the front and back services.
They constantly watch your files and rebuild the project automatically when there is any change.
Use `pm2 logs` to keep an eye on what's going on and `pm2 kill` to stop the services.
You can also use `pm2 ps` to check if the services are up and running.
For more, see the [PM2 documentation](https://pm2.keymetrics.io/docs/usage/quick-start/).
## Design
### Offline mode and Source of Truth (SoT)
While it is desirable to have a clear unique source of truth (SoT) for a tournament state, it has also deemed important
to be able to use this website in offline mode. Therefore, offline mode is activated _while online_ and changes the
source of truth (SoT) from the remote server to the local browser instance. This locks the remote server instance,
so noone else can interact with the server anymore.
Features deactivated in offline mode:
- Self registration for players
- Self check-in for players
- Score reporting for players
- Dynamic seating computation
Offline mode can be deactivated by any judge, so there are two "ways" out of it:
- Upload back online from the local instance that had been designated Source of Truth (SoT)
- Revert back to online from any other device and drop all changes from local Source of Truth (SoT)
### Journal and state
To facilitate reconciliation and avoid concurrency issues between multiple clients, the tournament state is maintained
and computed by the SoT. All instances (any browser, device, etc.) maintains a journal of events.
These events have unique IDs. On active interactions, an instance will:
- Send the event to the server, together with the last recorded event ID on the instance
- Receive an updated tournament state, together with a list of events since the last recorded event ID
- replay the listed events to modify the interface
In offline mode (being the SoT), it will simply:
- Play the events as they arrive
- Upon returning online, sent the updated state with all events
Online clients can either:
- Simply rebuild their whole interface any time they get a tournament state update after sending an event
- Apply all returned events in order to their interface to avoid a global reload
In the future, this design will allow clients to use websockets for live updates very easily.
### Events list
#### Register
Neither VEKN nor UID is mandatory. To register a new player who has no VEKN account, provide a new UUID4.
If you do not provide one, a new UUID4 will be generated and an account created for that person.
```json
{
"type": "Register",
"name": "John Doe",
"vekn": "12300001",
"player_uid": "24AAC87E-DE63-46DF-9784-AB06B2F37A24",
"country": "France",
"city": "Paris"
}
```
#### OpenCheckin
Check a player in, signaling they are present and ready to play the next round.
You should perform the check-in just before the round starts to limit the number of players
who do not show up to their table.
```json
{
"type": "OpenCheckin"
}
```
#### AppointJudge
Judges have permission to send all events, simple players are limited.
The UID must match a VEKN member UID.
```json
{
"type": "AppointJudge",
"judge_uid": "238CD960-7E54-4A38-A676-8288A5700FC8"
}
```
#### AppointJudge
Remove a judge.
```json
{
"type": "RemoveJudge",
"judge_uid": "238CD960-7E54-4A38-A676-8288A5700FC8"
}
```
#### CheckIn
Mark a player as ready to play. Players can self-check-in.
```json
{
"type": "CheckIn",
"player_uid": "238CD960-7E54-4A38-A676-8288A5700FC8"
}
```
#### RoundStart
Start the next round. The provided seating must list players UID forming the tables.
Each UID must match a VEKN member UID.
```json
{
"type": "RoundStart",
"seating": [
["238CD960-7E54-4A38-A676-8288A5700FC8",
"796CD3CE-BC2B-4505-B448-1C2D42E9F140",
"80E9FD37-AD8C-40AA-A42D-138065530F10",
"586616DC-3FEA-4DAF-A222-1E77A2CBD809",
"8F28E4C2-1953-473E-A1C5-C281957072D1"
],[
"BD570AA9-B70C-43CA-AD05-3B4C7DADC28C",
"AB6F75B3-ED60-45CA-BDFF-1BF8DD5F02C4",
"1CB1E9A7-576B-4065-8A9C-F7920AAF977D",
"8907BE41-91A7-4395-AF91-54D94C489A36"
]
]
}
```
#### RoundAlter
Change a round's seating. Note recorded VPs, if any, stay assigned to the player even if they move.
```json
{
"type": "RoundAlter",
"round": 1,
"seating": [
["238CD960-7E54-4A38-A676-8288A5700FC8",
"796CD3CE-BC2B-4505-B448-1C2D42E9F140",
"80E9FD37-AD8C-40AA-A42D-138065530F10",
"586616DC-3FEA-4DAF-A222-1E77A2CBD809",
"8F28E4C2-1953-473E-A1C5-C281957072D1"
],[
"BD570AA9-B70C-43CA-AD05-3B4C7DADC28C",
"AB6F75B3-ED60-45CA-BDFF-1BF8DD5F02C4",
"1CB1E9A7-576B-4065-8A9C-F7920AAF977D",
"8907BE41-91A7-4395-AF91-54D94C489A36"
]
]
}
```
#### RoundFinish
Finish the current round.
```json
{
"type": "RoundFinish"
}
```
#### SetResult
Set a player's result. Players can set their and their table result for the current round.
Only VPs are provided, the GW and TP computations are done by the engine.
```json
{
"type": "SetResult",
"player_uid": "238CD960-7E54-4A38-A676-8288A5700FC8",
"round": 1,
"vps": 2.5
}
```
#### Drop
Drop a player from the tournament. A player can drop by themselves.
A Judge can drop a player if they note they have juse left.
To **disqualify** a player, use the [Sanction](#sanction) event.
```json
{
"type": "Drop",
"player_uid": "238CD960-7E54-4A38-A676-8288A5700FC8"
}
```
#### Sanction
Sanction (punish) a player.
The sanction levels are: `CAUTION`, `WARNING` and `DISQUALIFICATION`.
Cautions are just informative. Warnings are recorded (accessible to organizers, even in future events).
Disqualifications are recorded and remove the player from the tournament.
Sanction also have an optional category, one of:
- `DECK_PROBLEM`
- `PROCEDURAL_ERRORS`
- `CARD_DRAWING`
- `MARKED_CARDS`
- `SLOW_PLAY`
- `UNSPORTSMANLIKE_CONDUCT`
- `CHEATING`
```json
{
"type": "Sanction",
"level": "WARNING",
"player_uid": "238CD960-7E54-4A38-A676-8288A5700FC8",
"comment": "Free comment",
"category": "PROCEDURAL_ERRORS"
}
```
#### Unsanction
Remove all sanctions of given level for a player.
```json
{
"type": "Unsanction",
"level": "WARNING",
"player_uid": "238CD960-7E54-4A38-A676-8288A5700FC8"
}
```
#### Override
Judges can validated an odd table score.
For example, if they disqualify a player but do not award VPs to their predator,
the final table score will not appear valid until it's overriden.
Rounds and tables are counted starting from 1.
```json
{
"type": "Override",
"round": 1,
"table": 1,
"comment": "Free form comment"
}
```
#### SeedFinals
A finals is "seeded" first before players elect their seat in seed order.
```json
{
"type": "SeedFinals",
"seeds": ["238CD960-7E54-4A38-A676-8288A5700FC8",
"796CD3CE-BC2B-4505-B448-1C2D42E9F140",
"80E9FD37-AD8C-40AA-A42D-138065530F10",
"586616DC-3FEA-4DAF-A222-1E77A2CBD809",
"8F28E4C2-1953-473E-A1C5-C281957072D1"
]
}
```
#### SeatFinals
Note what seating position finalists have elected.
```json
{
"type": "SeatFinals",
"seating": ["238CD960-7E54-4A38-A676-8288A5700FC8",
"796CD3CE-BC2B-4505-B448-1C2D42E9F140",
"80E9FD37-AD8C-40AA-A42D-138065530F10",
"586616DC-3FEA-4DAF-A222-1E77A2CBD809",
"8F28E4C2-1953-473E-A1C5-C281957072D1"
]
}
```
#### Finish
Finish the tournament. This closes up the tournament. The winner, if finals results have been recorded,
is automatically computed.
```json
{
"type": "Finish",
}
```
Raw data
{
"_id": null,
"home_page": null,
"name": "vtes-archon",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "vtes, Vampire: The Eternal Struggle, CCG, Tournament",
"author": "VEKN",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/9b/60/0dc9193740128ee087d866dd1d4e58182d3154d53eaabffdee9ae9f503a2/vtes_archon-0.5.tar.gz",
"platform": null,
"description": "# archon\n\nTournament management\n\n## Development install\n\nThis project uses [npm](https://docs.npmjs.com), that you can install with [nvm](https://github.com/nvm-sh/nvm).\nIt also uses [Python](https://docs.python.org/3/) on the backend side, so install Python version >= `3.11`.\n\nFinally, you'll need [GNU Make](https://www.gnu.org/software/make/manual/make.html) for simple targets and processes defined in a [Makefile](Makefile).\nFour options if you are on Windows:\n\n- Use [Chocolatey](https://chocolatey.org) as package manager and `choco install make`\n- Use the [Windows Subsystem for Linux (WSL)](https://learn.microsoft.com/en-us/windows/wsl/) feature\n- Just install the [GNU make binary for Windows](https://gnuwin32.sourceforge.net/packages/make.htm)\n- Don't use `make` at all. The [Makefile](Makefile) is just a shortcut, you can open it and copy/paste the commands in your Powershell.\n\n```bash\nnvm install node\nnvm use node\npython -m virtualenv .venv\nsource .venv/bin/activate\nmake update\n```\n\nWe are using a couple of very standard tools and frameworks, that `make update` will install and update for you:\n\n- [Typescript](https://www.typescriptlang.org/docs/) our frontend language\n\n- [Bootstrap](https://getbootstrap.com/docs) and its [icons](https://icons.getbootstrap.com), for basic styling & responsiveness \n\n- [Parcel](https://parceljs.org/docs/) as our build framework for frontend\n\n- [FastAPI](https://fastapi.tiangolo.com/learn/) as our backend server framework,\n with [Jinja2](https://jinja.palletsprojects.com/en/stable/) for HTML templating,\n its [i18n extension](https://jinja.palletsprojects.com/en/stable/extensions/#i18n-extension) for potential future translations,\n and [pyJWT](https://pyjwt.readthedocs.io/en/stable/) for generating [OAuth 2.0](https://oauth.net/2/) [JWT (RFC 7519)](https://datatracker.ietf.org/doc/html/rfc7519) tokens.\n\n- [PostgreSQL](https://www.postgresql.org/docs/current/index.html) for database,\n with [psycopg3](https://www.psycopg.org/psycopg3/docs/) as our library to instrument it\n\n- [AIOHTTP](https://docs.aiohttp.org) for web queries\n\n- [Black](https://black.readthedocs.io/en/stable/) and [Ruff](https://docs.astral.sh/ruff/) for python formatting and linting, respectively\n\n- [Twine](https://twine.readthedocs.io/en/stable/) to publish our Python package to the public [PYPI](https://pypi.org) repository.\n\n- [PM2](https://pm2.keymetrics.io/docs/usage/quick-start/) to run our hot reload development services (front & back)\n\n- [Geonames](https://www.geonames.org) for countries and cities names and IDs\n\n- [Typer](https://typer.tiangolo.com) for the [`archon` Command-Line Interface (CLI)](#cli)\n\n## Make targets\n\n- `make geodata` downlad and refresh the geographical data in [geodata](src/archon/geodata)\n- `make test` runs the tests, formatting and linting checks\n- `make serve` runs a dev server with watchers for auto-reload when changes are made to the source files\n- `make clean` cleans the repository from all transient build files\n- `make build` builds the python package\n- `make release` creates and pushes a git tag for this version and publishes the package on [PYPI](https://pypi.org)\n\n## CLI\n\nThe `archon` CLI gives access to useful DB-related commands when developing in local.\n\n```bash\n> archon --help\n\n Usage: archon [OPTIONS] COMMAND [ARGS]...\n\u256d\u2500 Options \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\n\u2502 --install-completion Install completion for the current shell. \u2502\n\u2502 --show-completion Show completion for the current shell, to copy it or customize the installation. \u2502\n\u2502 --help Show this message and exit. \u2502\n\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\n\u256d\u2500 Commands \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256e\n\u2502 list \u2502\n\u2502 purge \u2502\n\u2502 reset-db \u2502\n\u2502 sync-members \u2502\n\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\n```\n\n## Development database\n\nYou need a running [PostgreSQL](https://www.postgresql.org/docs/current/index.html) server, with an `archon` superuser,\nan `archondb` database owned by that superuser, with no password.\nYou can use the `DB_USER` and `DB_PWD` environment variables to use other values. The database name is not configurable.\n\n## Development server\n\nUse `openssl` to generate a secure token secret for signing our [JWT]() access tokens.\n\n```bash\nopenssl rand -hex 32\n```\n\nSet this value for the `TOKEN_SECRET` environment variable, for example in a `.env` file at the repository's root.\n\n```bash\nexport TOKEN_SECRET=\"[The generated secret string]\"\n```\n\nSimply use `make serve` to run the front and back services.\nThey constantly watch your files and rebuild the project automatically when there is any change.\nUse `pm2 logs` to keep an eye on what's going on and `pm2 kill` to stop the services.\nYou can also use `pm2 ps` to check if the services are up and running.\nFor more, see the [PM2 documentation](https://pm2.keymetrics.io/docs/usage/quick-start/).\n\n## Design \n\n### Offline mode and Source of Truth (SoT)\n\nWhile it is desirable to have a clear unique source of truth (SoT) for a tournament state, it has also deemed important\nto be able to use this website in offline mode. Therefore, offline mode is activated _while online_ and changes the\nsource of truth (SoT) from the remote server to the local browser instance. This locks the remote server instance,\nso noone else can interact with the server anymore.\n\nFeatures deactivated in offline mode:\n\n- Self registration for players\n- Self check-in for players\n- Score reporting for players\n- Dynamic seating computation\n\nOffline mode can be deactivated by any judge, so there are two \"ways\" out of it:\n\n- Upload back online from the local instance that had been designated Source of Truth (SoT)\n- Revert back to online from any other device and drop all changes from local Source of Truth (SoT)\n\n### Journal and state\n\nTo facilitate reconciliation and avoid concurrency issues between multiple clients, the tournament state is maintained\nand computed by the SoT. All instances (any browser, device, etc.) maintains a journal of events.\nThese events have unique IDs. On active interactions, an instance will:\n\n- Send the event to the server, together with the last recorded event ID on the instance\n- Receive an updated tournament state, together with a list of events since the last recorded event ID\n- replay the listed events to modify the interface\n\nIn offline mode (being the SoT), it will simply:\n\n- Play the events as they arrive\n- Upon returning online, sent the updated state with all events \n\nOnline clients can either:\n\n- Simply rebuild their whole interface any time they get a tournament state update after sending an event\n- Apply all returned events in order to their interface to avoid a global reload\n\nIn the future, this design will allow clients to use websockets for live updates very easily.\n\n### Events list\n\n#### Register\n\nNeither VEKN nor UID is mandatory. To register a new player who has no VEKN account, provide a new UUID4.\nIf you do not provide one, a new UUID4 will be generated and an account created for that person.\n\n```json\n{\n \"type\": \"Register\",\n \"name\": \"John Doe\",\n \"vekn\": \"12300001\",\n \"player_uid\": \"24AAC87E-DE63-46DF-9784-AB06B2F37A24\",\n \"country\": \"France\",\n \"city\": \"Paris\"\n}\n```\n\n#### OpenCheckin\n\nCheck a player in, signaling they are present and ready to play the next round.\nYou should perform the check-in just before the round starts to limit the number of players\nwho do not show up to their table.\n\n```json\n{\n \"type\": \"OpenCheckin\"\n}\n```\n\n#### AppointJudge\n\nJudges have permission to send all events, simple players are limited.\nThe UID must match a VEKN member UID.\n\n```json\n{\n \"type\": \"AppointJudge\",\n \"judge_uid\": \"238CD960-7E54-4A38-A676-8288A5700FC8\"\n}\n```\n\n#### AppointJudge\n\nRemove a judge.\n\n```json\n{\n \"type\": \"RemoveJudge\",\n \"judge_uid\": \"238CD960-7E54-4A38-A676-8288A5700FC8\"\n}\n```\n\n#### CheckIn\n\nMark a player as ready to play. Players can self-check-in. \n\n```json\n{\n \"type\": \"CheckIn\",\n \"player_uid\": \"238CD960-7E54-4A38-A676-8288A5700FC8\"\n}\n```\n\n#### RoundStart\n\nStart the next round. The provided seating must list players UID forming the tables.\nEach UID must match a VEKN member UID.\n\n```json\n{\n \"type\": \"RoundStart\",\n \"seating\": [\n [\"238CD960-7E54-4A38-A676-8288A5700FC8\",\n \"796CD3CE-BC2B-4505-B448-1C2D42E9F140\",\n \"80E9FD37-AD8C-40AA-A42D-138065530F10\",\n \"586616DC-3FEA-4DAF-A222-1E77A2CBD809\",\n \"8F28E4C2-1953-473E-A1C5-C281957072D1\"\n ],[\n \"BD570AA9-B70C-43CA-AD05-3B4C7DADC28C\",\n \"AB6F75B3-ED60-45CA-BDFF-1BF8DD5F02C4\",\n \"1CB1E9A7-576B-4065-8A9C-F7920AAF977D\",\n \"8907BE41-91A7-4395-AF91-54D94C489A36\"\n ]\n ]\n}\n```\n\n\n#### RoundAlter\n\nChange a round's seating. Note recorded VPs, if any, stay assigned to the player even if they move.\n\n```json\n{\n \"type\": \"RoundAlter\",\n \"round\": 1,\n \"seating\": [\n [\"238CD960-7E54-4A38-A676-8288A5700FC8\",\n \"796CD3CE-BC2B-4505-B448-1C2D42E9F140\",\n \"80E9FD37-AD8C-40AA-A42D-138065530F10\",\n \"586616DC-3FEA-4DAF-A222-1E77A2CBD809\",\n \"8F28E4C2-1953-473E-A1C5-C281957072D1\"\n ],[\n \"BD570AA9-B70C-43CA-AD05-3B4C7DADC28C\",\n \"AB6F75B3-ED60-45CA-BDFF-1BF8DD5F02C4\",\n \"1CB1E9A7-576B-4065-8A9C-F7920AAF977D\",\n \"8907BE41-91A7-4395-AF91-54D94C489A36\"\n ]\n ]\n}\n```\n\n#### RoundFinish\n\nFinish the current round.\n\n```json\n{\n \"type\": \"RoundFinish\"\n}\n```\n\n#### SetResult\n\nSet a player's result. Players can set their and their table result for the current round.\nOnly VPs are provided, the GW and TP computations are done by the engine.\n\n```json\n{\n \"type\": \"SetResult\",\n \"player_uid\": \"238CD960-7E54-4A38-A676-8288A5700FC8\",\n \"round\": 1,\n \"vps\": 2.5\n}\n```\n\n#### Drop\n\nDrop a player from the tournament. A player can drop by themselves.\nA Judge can drop a player if they note they have juse left.\nTo **disqualify** a player, use the [Sanction](#sanction) event.\n\n```json\n{\n \"type\": \"Drop\",\n \"player_uid\": \"238CD960-7E54-4A38-A676-8288A5700FC8\"\n}\n```\n\n#### Sanction\n\nSanction (punish) a player.\nThe sanction levels are: `CAUTION`, `WARNING` and `DISQUALIFICATION`.\nCautions are just informative. Warnings are recorded (accessible to organizers, even in future events).\nDisqualifications are recorded and remove the player from the tournament.\n\nSanction also have an optional category, one of:\n\n- `DECK_PROBLEM`\n- `PROCEDURAL_ERRORS`\n- `CARD_DRAWING`\n- `MARKED_CARDS`\n- `SLOW_PLAY`\n- `UNSPORTSMANLIKE_CONDUCT`\n- `CHEATING`\n\n```json\n{\n \"type\": \"Sanction\",\n \"level\": \"WARNING\",\n \"player_uid\": \"238CD960-7E54-4A38-A676-8288A5700FC8\",\n \"comment\": \"Free comment\",\n \"category\": \"PROCEDURAL_ERRORS\"\n}\n```\n \n#### Unsanction\n\nRemove all sanctions of given level for a player.\n\n```json\n{\n \"type\": \"Unsanction\",\n \"level\": \"WARNING\",\n \"player_uid\": \"238CD960-7E54-4A38-A676-8288A5700FC8\"\n}\n```\n\n#### Override\nJudges can validated an odd table score.\nFor example, if they disqualify a player but do not award VPs to their predator,\nthe final table score will not appear valid until it's overriden.\n\nRounds and tables are counted starting from 1.\n\n```json\n{\n \"type\": \"Override\",\n \"round\": 1,\n \"table\": 1,\n \"comment\": \"Free form comment\"\n}\n```\n\n#### SeedFinals\n\nA finals is \"seeded\" first before players elect their seat in seed order.\n\n```json\n{\n \"type\": \"SeedFinals\",\n \"seeds\": [\"238CD960-7E54-4A38-A676-8288A5700FC8\",\n \"796CD3CE-BC2B-4505-B448-1C2D42E9F140\",\n \"80E9FD37-AD8C-40AA-A42D-138065530F10\",\n \"586616DC-3FEA-4DAF-A222-1E77A2CBD809\",\n \"8F28E4C2-1953-473E-A1C5-C281957072D1\"\n ]\n}\n```\n \n#### SeatFinals\n\nNote what seating position finalists have elected.\n\n```json\n{\n \"type\": \"SeatFinals\",\n \"seating\": [\"238CD960-7E54-4A38-A676-8288A5700FC8\",\n \"796CD3CE-BC2B-4505-B448-1C2D42E9F140\",\n \"80E9FD37-AD8C-40AA-A42D-138065530F10\",\n \"586616DC-3FEA-4DAF-A222-1E77A2CBD809\",\n \"8F28E4C2-1953-473E-A1C5-C281957072D1\"\n ]\n}\n```\n\n#### Finish\n\nFinish the tournament. This closes up the tournament. The winner, if finals results have been recorded,\nis automatically computed.\n\n```json\n{\n \"type\": \"Finish\",\n}\n```\n",
"bugtrack_url": null,
"license": null,
"summary": "VTES tournament management",
"version": "0.5",
"project_urls": {
"Repository": "https://github.com/vtes-biased/archon"
},
"split_keywords": [
"vtes",
" vampire: the eternal struggle",
" ccg",
" tournament"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f8a0e0bbbcff74a277673eda3ffe47030e0fc795bc2ca1722cc52b9548e848f2",
"md5": "8129c160b8604b4099e784ba800d5fa9",
"sha256": "cd8497791541e4834f47f7e6302729abeb8eb71f2de5cae9e1dca394d0343a84"
},
"downloads": -1,
"filename": "vtes_archon-0.5-py3-none-any.whl",
"has_sig": false,
"md5_digest": "8129c160b8604b4099e784ba800d5fa9",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 2847055,
"upload_time": "2024-12-06T17:00:56",
"upload_time_iso_8601": "2024-12-06T17:00:56.994285Z",
"url": "https://files.pythonhosted.org/packages/f8/a0/e0bbbcff74a277673eda3ffe47030e0fc795bc2ca1722cc52b9548e848f2/vtes_archon-0.5-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "9b600dc9193740128ee087d866dd1d4e58182d3154d53eaabffdee9ae9f503a2",
"md5": "58acb5dd99d422ad72a2c124a2974e6e",
"sha256": "c83d8105993a73d0efeeac43f5dfca64054f902bb3f2b12cc42d996222526d32"
},
"downloads": -1,
"filename": "vtes_archon-0.5.tar.gz",
"has_sig": false,
"md5_digest": "58acb5dd99d422ad72a2c124a2974e6e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 2772729,
"upload_time": "2024-12-06T17:00:59",
"upload_time_iso_8601": "2024-12-06T17:00:59.119886Z",
"url": "https://files.pythonhosted.org/packages/9b/60/0dc9193740128ee087d866dd1d4e58182d3154d53eaabffdee9ae9f503a2/vtes_archon-0.5.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-06 17:00:59",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "vtes-biased",
"github_project": "archon",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "vtes-archon"
}