# Mah Jongg assignment and RC5 score-sheet utility

## Default movement profile

`mj-default-v1` uses the rule approved on 2026-08-13:

- East: stay at the same table (`0`)
- West: move forward two tables (`+2`)
- South: move back one table (`-1`)
- North: move forward one table (`+1`)

Movement wraps through the configured table range. The profile is a versioned
JSON file so a later rule cannot silently alter assignments already generated
for a competition.

## Roster input

The CSV columns are:

```text
player_id,player_name,start_table,start_seat
```

Player IDs must contain one to three digits. Round 1 must contain exactly one
E, W, S and N player at every table.

## Generate

```bash
python scripts/generate_mj_assignments.py roster.csv \
  --rounds 12 --output generated-sheets
```

The table count defaults to the highest `start_table` in the CSV. Use
`--tables` only when an event intentionally includes unused numbered tables
above that value.

The utility produces:

- assignments by player;
- assignments by round;
- an input/profile checksum and generation manifest; and
- a prefilled letter-size PDF based on the supplied `MJ_RC5_2up.pdf` master.

The PDF is player-major. For 12 rounds, each player's six pages pair R1/R7,
R2/R8, R3/R9, R4/R10, R5/R11 and R6/R12. The bottom overlay is rotated 180
degrees to match the approved 2-up source. Printing and cutting therefore
creates the two ordered piles used by the organizer.

## Validation

Generation stops if IDs repeat, a starting position is missing or duplicated,
or any generated round fails to contain exactly one player in each seat at
each table.

Run the automated tests with:

```bash
python -m unittest discover -s tests -v
```
