Move the game-independent machinery (lobby, live-game store, websocket, deadline scheduler, match history, leaderboards) into a new tavolo-platform distribution behind a GameEngine contract, the scopone scientifico rules plus a platform adapter into tavolo-scopone, and keep only the composition root in tavolo-app. The three distributions share the tavolo namespace (PEP 420, kaya-style monorepo). Match history becomes fully generic: Match carries the engine's result JSON and MatchPlayer points/details instead of scopone-shaped team columns (migration 3 backfills existing rows). Lobby creation takes an opaque per-game options object and websocket actions dispatch to the session's engine. Tests: platform suite runs against a DummyEngine toy game, scopone keeps the rules tests plus new adapter tests, server/tests covers the wired stack end to end (194 tests, was 143).
74 lines
4.1 KiB
Python
74 lines
4.1 KiB
Python
from tortoise import BaseDBAsyncClient
|
|
|
|
RUN_IN_TRANSACTION = True
|
|
|
|
|
|
async def upgrade(db: BaseDBAsyncClient) -> str:
|
|
return """
|
|
ALTER TABLE "match" ADD "result" JSONB NOT NULL DEFAULT '{}';
|
|
UPDATE "match" SET "result" = jsonb_build_object(
|
|
'team_a_score', team_a_score,
|
|
'team_b_score', team_b_score,
|
|
'winner_team', winner_team,
|
|
'target_score', target_score,
|
|
'hands_played', hands_played);
|
|
ALTER TABLE "match" DROP COLUMN "winner_team";
|
|
ALTER TABLE "match" DROP COLUMN "team_b_score";
|
|
ALTER TABLE "match" DROP COLUMN "team_a_score";
|
|
ALTER TABLE "match" DROP COLUMN "target_score";
|
|
ALTER TABLE "match" DROP COLUMN "hands_played";
|
|
ALTER TABLE "match" ALTER COLUMN "game_type" DROP DEFAULT;
|
|
ALTER TABLE "match_player" ADD "details" JSONB NOT NULL DEFAULT '{}';
|
|
ALTER TABLE "match_player" ADD "score" DOUBLE PRECISION NOT NULL DEFAULT 0;
|
|
UPDATE "match_player" mp SET "score" = CASE WHEN mp.team = 'A'
|
|
THEN (mp_match.result->>'team_a_score')::float
|
|
ELSE (mp_match.result->>'team_b_score')::float END
|
|
FROM "match" mp_match WHERE mp_match.id = mp.match_id;
|
|
ALTER TABLE "match_player" ALTER COLUMN "team" DROP NOT NULL;
|
|
ALTER TABLE "match_player" ALTER COLUMN "team" TYPE VARCHAR(32) USING "team"::VARCHAR(32);"""
|
|
|
|
|
|
async def downgrade(db: BaseDBAsyncClient) -> str:
|
|
return """
|
|
ALTER TABLE "match" ADD "winner_team" VARCHAR(1) NOT NULL;
|
|
ALTER TABLE "match" ADD "team_b_score" SMALLINT NOT NULL;
|
|
ALTER TABLE "match" ADD "team_a_score" SMALLINT NOT NULL;
|
|
ALTER TABLE "match" ADD "target_score" SMALLINT NOT NULL;
|
|
ALTER TABLE "match" ADD "hands_played" SMALLINT NOT NULL;
|
|
ALTER TABLE "match" DROP COLUMN "result";
|
|
ALTER TABLE "match" ALTER COLUMN "game_type" SET DEFAULT 'scopone_scientifico';
|
|
ALTER TABLE "match_player" DROP COLUMN "details";
|
|
ALTER TABLE "match_player" DROP COLUMN "score";
|
|
ALTER TABLE "match_player" ALTER COLUMN "team" SET NOT NULL;
|
|
ALTER TABLE "match_player" ALTER COLUMN "team" TYPE VARCHAR(1) USING "team"::VARCHAR(1);"""
|
|
|
|
|
|
MODELS_STATE = (
|
|
"eJztmm1v4jgQx79KlFc9aa8C+rQ6rU4KlGq5hVIB3TttVUUmMdSqsbOOc13U63c/23l2El"
|
|
"ooUKj6piVjj+P8hoz/HvNozqgLsX/YA9y5M/8wHk0CZlB8yDd8MkzgealZGjgY47Bn0mXs"
|
|
"cwYcLowTgH0oTC70HYY8jiiRXS3DoTMPQw5dQ7kZdGJQAuU/fgcNBqfI55CJ5qmYh8HnHv"
|
|
"QP5dgudcTgiExfN0xA0M8A2pxOoejIxGA3t8KMiAt/QT++9O7tCYLYzQFBrhxA2W05oLRd"
|
|
"X3fOL1RPOcWx7VAczEja25vzO0qS7kGA3EPpI9umkEAGxCNkcJEA4whrbApnLAycBTCZqp"
|
|
"saXDgBAZbQzS+TgDiStaHuJP8c/xlNLdPNti/7I3vYHtm2WYiRnILGOzI5lMj4IsIlqMen"
|
|
"cNwUiLKa8gatr9bg4Oj0N4WA+nzKVKPCZT4pR8BB6Kqgp5RlvEJeBditO8DKYeecNOZiyq"
|
|
"vQjg0LcMekNsBWvFO/bAzJlMuX8qixgPV3axDibijcVLyA4Wt5GbU0VJOknlL2OWCChQ14"
|
|
"EfO5oMTRDJajzntqrN3I9TD+sB7yaTLZAvoFqEedXns4snpXcviZ7//Eipc1asuWhrLONe"
|
|
"vBqRaWZBDj787oqyEvjR/9y7b+riT9Rj9MOScQcGoT+mADN8skNsemXJgniCD/bqU4a64f"
|
|
"gd7pQIuhJJtCjP8a9i/L45t66KFFDjf+M7BYQDcV1Mw6NQ4Q5oj4h/K2b7FUSUK5KMdp86"
|
|
"Bn/aNn1Fa339TDJwdoivQqdcPkPrOmScMYOPcPgLl2riWNm4fBHDK/GLhm5HjxbQAxUM9b"
|
|
"DFVWol2pkfb3NUyt0VKrgNIGrSJabJo1ZroFEDBVjyTvLe9UgqxK9KZEn5G+tpf2fFYBX4"
|
|
"nlEznIUzGNZWvgQ2Ygoj6rIYuSdwm/Eo17k4p06WP7wdi8/RC+uyR8k7gsoXuzPu9P9jZO"
|
|
"Tl6ge0WvSuGr2vLK10W+fF1tdb0Eat1vU7i3mns13rXaS3jXatW8ZZu204Bl2nM4Axh3CK"
|
|
"/YY8BS0SnXhj1kPJWT+P2ocXb6WbSqOcqLswWshz2r2+1cjjSWHILZMt/ZuP9K39Xovd8Z"
|
|
"jBveET+ECktTYZRiCEg53YdSTTYWLnv4LV2As9nvd3MKudkZaVyve8324KCucItOiCtz8Q"
|
|
"vsO5SVZN0LTEFVKog9NMwT6bIpzrXtQz7vXze7beNq0G51hp1oS5JsMVVjHu6gbXU1uhBT"
|
|
"MWfMwbL5Nue4UtLdtWSxvpzrQg4QLtmhVW+tMy4fe+u17K2zAQm3XMvtSbI+69yZ7G7Sfm"
|
|
"YjUihWaHxLcrTIw2hKvsG5QtwREwHEKUvN+sHRfkIt1COEmYGHZHuc+06JpxfPDMPM3LKG"
|
|
"Leu8bT5VF4A2WdoIyxYDwMOHLNQ2cu2fFhU3wrKGzdKuz1Y3WgFjkHCjjakR+sWlinAwY0"
|
|
"KZukyO5YqVjhXHKK16ZDfI6SGRXvm4yR8gRQ98+1EQ+SiIvHU22kJFZHdPXN/VBjNNo3nG"
|
|
"lao8ddheHaR+UtvU5ifS5I368dnx56PT40SYJ5ZF6rwozNX6C/2w+F6SkCu5Fh23x3df4A"
|
|
"aePNhd5dw47/kOj41NBoHbJ3gerbv7e4ycnLK98Nhyk6rVggyV/wAtalmoVEHa5zmJWh3n"
|
|
"Nf80rDL/lOrBkpwTibrXCcHNF1lemXOq9d+/kPmorCpbrUoyLu9Qk2xE/cmXagnCUfd3SL"
|
|
"f+otOv+oLTr3rx9EvckUOy1A9zMi7brx6+TbHqLX6Ds/7F7Ol/ruuC3w=="
|
|
)
|