Skip to content

Commit

Permalink
On import, compute the eliminating team.
Browse files Browse the repository at this point in the history
If one team ends up eliminating the other, store that in the database so it gets a 10k bonus.
  • Loading branch information
EboMike committed Sep 20, 2024
1 parent eff7be4 commit c7722f4
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 49 deletions.
46 changes: 46 additions & 0 deletions helpers/sm5helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,52 @@ async def get_sm5_rating_over_time(entity_id: str, min_time: datetime = _MIN_DAT
)


async def get_sm5_last_team_standing(game: SM5Game) -> Optional[Team]:
"""Returns the team that eliminated the other team.
Returns an empty value if no team eliminated the other."""
alive_player_count = {}
entities = await game.entity_starts.all()

for entity in entities:
player = await SM5Stats.filter(entity__id=entity.id).first()

if player and player.lives_left > 0:
alive_player_count[(await entity.team).enum] = True

# If there isn't exactly one team with alive players at the end, this wasn't an elimination game.
if len(alive_player_count) != 1:
return None

return next(iter(alive_player_count.keys()))


async def compute_sm5_elimination_bonus(game: SM5Game) -> SM5Game:
"""Adds 10,000 points to the score of a team if it eliminated the others.
Will also recompute the winner of the game.
Will not do anything if the game ended early.
NOTE that this will update the database with the new values if a change was made! Don't call this twice on the same
game.
"""
# Nop if the game ended early.
if game.ended_early:
return game

eliminating_team = await get_sm5_last_team_standing(game)

if not eliminating_team:
# No elimination. Do nothing.
return game

# Add the bonus.
game.scores




def _create_lives_snapshot(lives_timeline: dict[int, list[int]], current_lives: dict[int, int]):
for entity_end_id, lives in current_lives.items():
lives_timeline[entity_end_id].append(lives)
Expand Down
40 changes: 18 additions & 22 deletions helpers/tdfhelper.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
from asyncio import Event

from db.player import Player
from db.game import EntityEnds, EntityStarts, Events, Scores, PlayerStates, Teams
from db.types import EventType, PlayerStateType, Team
from db.sm5 import SM5Game, SM5Stats, IntRole
from db.laserball import LaserballGame, LaserballStats
from helpers.ratinghelper import MU, SIGMA
from typing import List, Dict
from datetime import datetime
from sanic.log import logger
from helpers import ratinghelper
import aiohttp
import json
import os
from datetime import datetime
Expand All @@ -21,9 +8,12 @@
from db.game import EntityEnds, EntityStarts, Events, Scores, PlayerStates, Teams
from db.laserball import LaserballGame, LaserballStats
from db.player import Player
from db.sm5 import IntRole, SM5_LASERRANK_VERSION
from db.sm5 import SM5Game, SM5Stats
from db.types import EventType, PlayerStateType, Team
from helpers import ratinghelper
from helpers.ratinghelper import MU, SIGMA
from helpers.sm5helper import get_sm5_last_team_standing


def element_to_color(element: str) -> str:
Expand Down Expand Up @@ -224,20 +214,26 @@ async def parse_sm5_game(file_location: str) -> SM5Game:

logger.debug("Inital game save complete")

# Determine whether one team eliminated the other.
game.last_team_standing = await get_sm5_last_team_standing(game)

# winner determination

winner = None
red_score = await game.get_team_score(Team.RED)
green_score = await game.get_team_score(Team.GREEN)
if red_score > green_score:
winner = Team.RED
elif red_score < green_score:
winner = Team.GREEN
else: # tie or no winner or something crazy happened
winner = None
winner = game.last_team_standing

if not winner:
red_score = await game.get_team_score(Team.RED)
green_score = await game.get_team_score(Team.GREEN)
if red_score > green_score:
winner = Team.RED
elif red_score < green_score:
winner = Team.GREEN
else: # tie or no winner or something crazy happened
winner = None

game.winner = winner
game.winner_color = winner.value if winner else "none"
game.laserrank_version = SM5_LASERRANK_VERSION
await game.save()

logger.debug(f"Winner: {game.winner_color}")
Expand Down
107 changes: 80 additions & 27 deletions tests/helpers/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from db.game import Events, EntityStarts, Teams, EntityEnds, Scores
from db.laserball import LaserballGame
from db.sm5 import SM5Game
from db.sm5 import SM5Game, SM5Stats
from db.types import EventType, Team
from helpers.tdfhelper import create_event_from_data

Expand Down Expand Up @@ -166,19 +166,19 @@ async def create_resupply_lives_event(time_millis: int, supplier_entity_id: str,


async def add_entity(
entity_id: str,
team: Teams,
start_time_millis: int = 0,
end_time_millis: int = 900000,
type: str = "player",
name: str = "Some Player",
level: int = 0,
role: int = 0,
battlesuit: str = "Panther",
member_id: str = "4-43-000",
score: int = 0,
sm5_game: Optional[SM5Game] = None,
omit_entity_end: bool = False,
entity_id: str,
team: Teams,
start_time_millis: int = 0,
end_time_millis: int = 900000,
type: str = "player",
name: str = "Some Player",
level: int = 0,
role: int = 0,
battlesuit: str = "Panther",
member_id: str = "4-43-000",
score: int = 0,
sm5_game: Optional[SM5Game] = None,
omit_entity_end: bool = False,
) -> (EntityStarts, Optional[EntityEnds]):
entity_start = await create_entity_start(
entity_id=entity_id,
Expand Down Expand Up @@ -210,15 +210,15 @@ async def add_entity(


async def create_entity_start(
entity_id: str,
team: Teams,
time_millis: int = 0,
type: str = "player",
name: str = "Some Player",
level: int = 0,
role: int = 0,
battlesuit: str = "Panther",
member_id: str = "4-43-000"
entity_id: str,
team: Teams,
time_millis: int = 0,
type: str = "player",
name: str = "Some Player",
level: int = 0,
role: int = 0,
battlesuit: str = "Panther",
member_id: str = "4-43-000"
) -> EntityStarts:
return await EntityStarts.create(time=time_millis,
entity_id=entity_id,
Expand All @@ -231,11 +231,64 @@ async def create_entity_start(
member_id=member_id)


async def add_sm5_stats(entity_start: EntityStarts,
shots_hit: int = 0,
shots_fired: int = 0,
times_zapped: int = 0,
times_missiled: int = 0,
missile_hits: int = 0,
nukes_detonated: int = 0,
nukes_activated: int = 0,
nuke_cancels: int = 0,
medic_hits: int = 0,
own_medic_hits: int = 0,
medic_nukes: int = 0,
scout_rapid_fires: int = 0,
life_boosts: int = 0,
ammo_boosts: int = 0,
lives_left: int = 15,
shots_left: int = 0,
penalties: int = 0,
shot_3_hits: int = 0,
own_nuke_cancels: int = 0,
shot_opponent: int = 0,
shot_team: int = 0,
missiled_opponent: int = 0,
missiled_team: int = 0,
) -> SM5Stats:
return await SM5Stats.create(
entity=entity_start,
shots_hit=shots_hit,
shots_fired=shots_fired,
times_zapped=times_zapped,
times_missiled=times_missiled,
missile_hits=missile_hits,
nukes_detonated=nukes_detonated,
nukes_activated=nukes_activated,
nuke_cancels=nuke_cancels,
medic_hits=medic_hits,
own_medic_hits=own_medic_hits,
medic_nukes=medic_nukes,
scout_rapid_fires=scout_rapid_fires,
life_boosts=life_boosts,
ammo_boosts=ammo_boosts,
lives_left=lives_left,
shots_left=shots_left,
penalties=penalties,
shot_3_hits=shot_3_hits,
own_nuke_cancels=own_nuke_cancels,
shot_opponent=shot_opponent,
shot_team=shot_team,
missiled_opponent=missiled_opponent,
missiled_team=missiled_team,
)


async def create_entity_ends(
entity_start: EntityStarts,
time_millis: int = 90000,
type: int = 1,
score: int = 0) -> EntityEnds:
entity_start: EntityStarts,
time_millis: int = 90000,
type: int = 1,
score: int = 0) -> EntityEnds:
return await EntityEnds.create(time=time_millis,
entity=entity_start,
type=type,
Expand Down
49 changes: 49 additions & 0 deletions tests/helpers/sm5helper_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import unittest

from db.sm5 import SM5Game
from db.types import Team
from helpers.sm5helper import get_sm5_last_team_standing
from tests.helpers.environment import setup_test_database, ENTITY_ID_1, ENTITY_ID_2, get_sm5_game_id, \
teardown_test_database, add_entity, get_red_team, get_green_team, add_sm5_stats


class TestSm5Helper(unittest.IsolatedAsyncioTestCase):
async def asyncSetUp(self):
await setup_test_database()

async def asyncTearDown(self):
await teardown_test_database()

async def test_get_sm5_last_team_standing_both_alive(self):
game = await SM5Game.filter(id=get_sm5_game_id()).first()
entity_start, entity_end = await add_entity(entity_id=ENTITY_ID_1, team=get_red_team())
stats = await add_sm5_stats(entity_start, lives_left=10)

entity_start2, entity_end2 = await add_entity(entity_id=ENTITY_ID_2, team=get_green_team())
stats2 = await add_sm5_stats(entity_start2, lives_left=15)

await game.entity_starts.add(entity_start, entity_start2)
game = await SM5Game.filter(id=get_sm5_game_id()).first()

winning_team = await get_sm5_last_team_standing(game)

self.assertEqual(None, winning_team)

async def test_get_sm5_last_team_standing_only_red_alive(self):
game = await SM5Game.filter(id=get_sm5_game_id()).first()
entity_start, entity_end = await add_entity(entity_id=ENTITY_ID_1, team=get_red_team())
await add_sm5_stats(entity_start, lives_left=10)

entity_start2, entity_end2 = await add_entity(entity_id=ENTITY_ID_2, team=get_green_team())
await add_sm5_stats(entity_start2, lives_left=0)

await game.entity_starts.add(entity_start, entity_start2)
game = await SM5Game.filter(id=get_sm5_game_id()).first()

winning_team = await get_sm5_last_team_standing(game)

self.assertEqual(Team.RED, winning_team)


if __name__ == '__main__':
unittest.main()

0 comments on commit c7722f4

Please sign in to comment.