Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DECAPITATION as rated victory condition #1040

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
- cron: '0 0 * * *'

env:
FAF_DB_VERSION: v133
FAF_DB_VERSION: v136
FLYWAY_VERSION: 7.5.4

jobs:
Expand Down
9 changes: 5 additions & 4 deletions server/db/typedefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@

@unique
class Victory(Enum):
DEMORALIZATION = 0
DOMINATION = 1
ERADICATION = 2
SANDBOX = 3
DEMORALIZATION = "DEMORALIZATION"
DOMINATION = "DOMINATION"
ERADICATION = "ERADICATION"
SANDBOX = "SANDBOX"
DECAPITATION = "DECAPITATION"


@unique
Expand Down
12 changes: 7 additions & 5 deletions server/games/game.py
Original file line number Diff line number Diff line change
Expand Up @@ -692,10 +692,12 @@ async def validate_game_mode_settings(self):
await self.mark_invalid(ValidityState.UNEVEN_TEAMS_NOT_RANKED)
return

valid_options = {
"Victory": (Victory.DEMORALIZATION, ValidityState.WRONG_VICTORY_CONDITION)
}
await self._validate_game_options(valid_options)
if self.game_options.get("Victory") not in (
Victory.DEMORALIZATION,
Victory.DECAPITATION,
):
await self.mark_invalid(ValidityState.WRONG_VICTORY_CONDITION)
return

async def _validate_game_options(
self,
Expand Down Expand Up @@ -757,7 +759,7 @@ async def update_game_stats(self):
# In some cases, games can be invalidated while running: we check for
# those cases when the game ends and update this record as appropriate.

game_type = str(self.game_options.get("Victory").value)
Askaholic marked this conversation as resolved.
Show resolved Hide resolved
game_type = self.game_options.get("Victory")

async with self._db.acquire() as conn:
await conn.execute(
Expand Down
44 changes: 22 additions & 22 deletions tests/data/test-data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -197,28 +197,28 @@ insert into game_featuredMods (id, gamemod, name, description, publish, git_url,
(25, 'coop', 'Coop', 'Multiplayer campaign games', 1, 'https://github.com/FAForever/fa-coop.git', 'master', 'cop', TRUE);

insert into game_stats (id, startTime, gameName, gameType, gameMod, host, mapId, validity) values
(1, NOW(), 'Test game', '0', 6, 1, 1, 0),
(41935, NOW(), 'MapRepetition', '0', 6, 1, NULL, 0),
(41936, NOW() + interval 1 minute, 'MapRepetition', '0', 6, 1, 1, 0),
(41937, NOW() + interval 2 minute, 'MapRepetition', '0', 6, 1, 2, 0),
(41938, NOW() + interval 3 minute, 'MapRepetition', '0', 6, 1, 3, 0),
(41939, NOW() + interval 4 minute, 'MapRepetition', '0', 6, 1, 4, 0),
(41940, NOW() + interval 5 minute, 'MapRepetition', '0', 6, 1, 5, 0),
(41941, NOW() + interval 6 minute, 'MapRepetition', '0', 6, 1, 6, 0),
(41942, NOW(), 'OldRatingNull', '0', 6, 1, NULL, 0),
(41943, NOW(), 'OldRatingLose', '0', 6, 1, NULL, 0),
(41944, NOW(), 'OldRatingWin', '0', 6, 1, NULL, 0),
(41945, NOW() + interval 7 minute, 'MapRepetition', '0', 6, 2, 6, 0),
(41946, NOW() + interval 8 minute, 'MapRepetition', '0', 6, 2, 5, 0),
(41947, NOW() + interval 9 minute, 'MapRepetition', '0', 6, 2, 4, 0),
(41948, NOW() + interval 10 minute, 'MapRepetition', '0', 6, 2, 3, 0),
(41949, NOW() + interval 1 minute, 'MapRepetition', '0', 6, 1, 7, 0),
(41950, NOW() + interval 2 minute, 'MapRepetition', '0', 6, 1, 8, 0),
(41951, NOW() + interval 3 minute, 'MapRepetition', '0', 6, 1, 9, 0),
(41952, NOW() + interval 4 minute, 'MapRepetition', '0', 6, 1, 7, 0),
(41953, NOW() + interval 1 minute, 'MapRepetition', '0', 6, 2, 5, 0),
(41954, NOW() + interval 2 minute, 'MapRepetition', '0', 6, 2, 6, 0),
(41955, NOW() + interval 3 minute, 'MapRepetition', '0', 6, 2, 7, 0);
(1, NOW(), 'Test game', 'DEMORALIZATION', 6, 1, 1, 0),
(41935, NOW(), 'MapRepetition', 'DEMORALIZATION', 6, 1, NULL, 0),
(41936, NOW() + interval 1 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 1, 0),
(41937, NOW() + interval 2 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 2, 0),
(41938, NOW() + interval 3 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 3, 0),
(41939, NOW() + interval 4 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 4, 0),
(41940, NOW() + interval 5 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 5, 0),
(41941, NOW() + interval 6 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 6, 0),
(41942, NOW(), 'OldRatingNull', 'DEMORALIZATION', 6, 1, NULL, 0),
(41943, NOW(), 'OldRatingLose', 'DEMORALIZATION', 6, 1, NULL, 0),
(41944, NOW(), 'OldRatingWin', 'DEMORALIZATION', 6, 1, NULL, 0),
(41945, NOW() + interval 7 minute, 'MapRepetition', 'DEMORALIZATION', 6, 2, 6, 0),
(41946, NOW() + interval 8 minute, 'MapRepetition', 'DEMORALIZATION', 6, 2, 5, 0),
(41947, NOW() + interval 9 minute, 'MapRepetition', 'DEMORALIZATION', 6, 2, 4, 0),
(41948, NOW() + interval 10 minute, 'MapRepetition', 'DEMORALIZATION', 6, 2, 3, 0),
(41949, NOW() + interval 1 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 7, 0),
(41950, NOW() + interval 2 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 8, 0),
(41951, NOW() + interval 3 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 9, 0),
(41952, NOW() + interval 4 minute, 'MapRepetition', 'DEMORALIZATION', 6, 1, 7, 0),
(41953, NOW() + interval 1 minute, 'MapRepetition', 'DEMORALIZATION', 6, 2, 5, 0),
(41954, NOW() + interval 2 minute, 'MapRepetition', 'DEMORALIZATION', 6, 2, 6, 0),
(41955, NOW() + interval 3 minute, 'MapRepetition', 'DEMORALIZATION', 6, 2, 7, 0);

insert into game_player_stats (gameId, playerId, AI, faction, color, team, place, mean, deviation, scoreTime) values
(1, 1, 0, 0, 0, 2, 0, 1500, 500, NOW()),
Expand Down
84 changes: 82 additions & 2 deletions tests/integration_tests/test_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ async def host_game(
*,
mod: str = "faf",
visibility: str = "public",
game_options: dict = {},
**kwargs
) -> int:
await proto.send_message({
Expand All @@ -42,6 +43,13 @@ async def host_game(
await open_fa(proto)
await read_until_command(proto, "HostGame", target="game")

for option, value in game_options.items():
await proto.send_message({
"target": "game",
"command": "GameOption",
"args": [option, value],
})

return game_id


Expand All @@ -62,10 +70,16 @@ async def setup_game_1v1(
guest_proto: Protocol,
guest_id: int,
mod: str = "faf",
game_options: dict = {},
**kwargs,
):
# Set up the game
game_id = await host_game(host_proto, mod=mod, **kwargs)
game_id = await host_game(
host_proto,
mod=mod,
game_options=game_options,
**kwargs,
)
await join_game(guest_proto, game_id)
# Set player options
await send_player_options(
Expand Down Expand Up @@ -552,7 +566,7 @@ async def test_game_ended_broadcasts_rating_update(lobby_server, channel):


@fast_forward(60)
async def test_neroxis_map_generator_rates_game(lobby_server):
async def test_neroxis_map_generator_game_rated(lobby_server):
host_id, _, host_proto = await connect_and_sign_in(
("test", "test_password"), lobby_server
)
Expand Down Expand Up @@ -615,6 +629,72 @@ async def test_neroxis_map_generator_rates_game(lobby_server):
await read_until_command(host_proto, "player_info", timeout=10)


@fast_forward(60)
async def test_decapitation_game_rated(lobby_server):
host_id, _, host_proto = await connect_and_sign_in(
("test", "test_password"), lobby_server
)
guest_id, _, guest_proto = await connect_and_sign_in(
("Rhiza", "puff_the_magic_dragon"), lobby_server
)
await read_until_command(guest_proto, "game_info")
ratings = await get_player_ratings(host_proto, "test", "Rhiza")

await setup_game_1v1(
host_proto,
host_id,
guest_proto,
guest_id,
game_options={
"Victory": "decapitation",
}
)
await host_proto.send_message({
"target": "game",
"command": "EnforceRating",
"args": []
})

# End the game
# Reports results
for proto in (host_proto, guest_proto):
await proto.send_message({
"target": "game",
"command": "GameResult",
"args": [1, "victory 10"]
})
await proto.send_message({
"target": "game",
"command": "GameResult",
"args": [2, "defeat -10"]
})
# Report GameEnded
for proto in (host_proto, guest_proto):
await proto.send_message({
"target": "game",
"command": "GameEnded",
"args": []
})

# Check that the ratings were updated
new_ratings = await get_player_ratings(host_proto, "test", "Rhiza")

assert ratings["test"][0] < new_ratings["test"][0]
assert ratings["Rhiza"][0] > new_ratings["Rhiza"][0]

# Now disconnect both players
for proto in (host_proto, guest_proto):
await proto.send_message({
"target": "game",
"command": "GameState",
"args": ["Ended"]
})

# The game should only be rated once
with pytest.raises(asyncio.TimeoutError):
await read_until_command(host_proto, "player_info", timeout=10)


@fast_forward(30)
async def test_double_host_message(lobby_server):
_, _, proto = await connect_and_sign_in(
Expand Down
Loading