1+ from sanic import Request
2+ from sanic .log import logger
3+
4+ from db .sm5 import SM5Game
5+ from db .laserball import LaserballGame
6+ from helpers import ratinghelper
7+ from db .types import IntRole
8+ from shared import app
9+ from utils import admin_only
10+
11+ @app .post ("/admin/audit_ranked_status/<type:str>" )
12+ @admin_only
13+ async def audit_ranked_status (request : Request , type : str ) -> str :
14+ response = await request .respond (content_type = "text/html" )
15+
16+ logger .info (f"Starting ranked status audit for type: { type } " )
17+
18+ # type is either "sm5" or "laserball" or "all"
19+
20+ if type not in ["sm5" , "laserball" , "all" ]:
21+ return response .json ({"status" : "error" , "message" : "Invalid type" })
22+
23+ # go through each game and check ranked eligibility
24+ if type in ["sm5" , "all" ]:
25+ sm5_games = await SM5Game .all ().order_by ("-start_time" )
26+ for game in sm5_games :
27+ # maybe eventually make elgibility criteria in a helper function
28+
29+ ranked = True
30+
31+ teams = await game .teams .all ()
32+ entity_starts = await game .entity_starts .all ()
33+
34+ team1 = None
35+ team2 = None
36+
37+ index = 1
38+
39+ for t in teams :
40+ if not t .color_name or not t .color_enum or t .name == "Neutral" :
41+ continue
42+
43+ if index == 1 :
44+ team1 = t
45+ else : # 2
46+ team2 = t
47+
48+ index += 1
49+
50+ team1_len = await game .entity_ends .filter (entity__team = team1 , entity__type = "player" ).count ()
51+ team2_len = await game .entity_ends .filter (entity__team = team2 , entity__type = "player" ).count ()
52+
53+ if team1_len > 7 or team2_len > 7 or team1_len < 5 or team2_len < 5 or team1_len != team2_len :
54+ ranked = False
55+
56+
57+ for t in teams :
58+ total_count = 0
59+ commander_count = 0
60+ heavy_count = 0
61+ scout_count = 0
62+ ammo_count = 0
63+ medic_count = 0
64+
65+ for e in entity_starts :
66+ if e .type == "player" and e .team == t :
67+ total_count += 1
68+ if e .role == IntRole .COMMANDER :
69+ commander_count += 1
70+ elif e .role == IntRole .HEAVY :
71+ heavy_count += 1
72+ elif e .role == IntRole .SCOUT :
73+ scout_count += 1
74+ elif e .role == IntRole .AMMO : # sometimes we have 2 ammos, but for ranking purposes we only want games with 1
75+ ammo_count += 1
76+ elif e .role == IntRole .MEDIC :
77+ medic_count += 1
78+
79+ if total_count == 0 : # probably a neutral team
80+ continue
81+
82+ if commander_count != 1 or heavy_count != 1 or ammo_count != 1 or medic_count != 1 or scout_count < 1 or scout_count > 3 :
83+ ranked = False
84+
85+
86+ for e in entity_starts :
87+ if e .type == "player" and e .entity_id .startswith ("@" ) and e .name == e .battlesuit :
88+ ranked = False
89+ break
90+
91+ if ranked != game .ranked :
92+ logger .info (f"SM5 Game ID { game .id } ranked status changed from { game .ranked } to { ranked } " )
93+ game .ranked = ranked
94+ await game .save ()
95+
96+ # unranked -> ranked
97+
98+ if ranked :
99+ await ratinghelper .update_sm5_ratings (game )
100+
101+ if type in ["laserball" , "all" ]:
102+ laserball_games = await LaserballGame .all ().order_by ("-start_time" )
103+ for game in laserball_games :
104+ ranked = True
105+
106+ teams = await game .teams .all ()
107+ entity_starts = await game .entity_starts .all ()
108+
109+ team1 = None
110+ team2 = None
111+
112+ index = 1
113+
114+ for t in teams :
115+ if not t .color_name or not t .color_enum or t .name == "Neutral" :
116+ continue
117+
118+ if index == 1 :
119+ team1 = t
120+ else : # 2
121+ team2 = t
122+
123+ index += 1
124+
125+ team1_len = await game .entity_ends .filter (entity__team = team1 , entity__type = "player" ).count ()
126+ team2_len = await game .entity_ends .filter (entity__team = team2 , entity__type = "player" ).count ()
127+
128+ if team1_len < 2 or team2_len < 2 :
129+ ranked = False
130+
131+ for e in entity_starts :
132+ if e .type == "player" and e .entity_id .startswith ("@" ) and e .name == e .battlesuit :
133+ logger .debug (f"Found non-member player { e .name } , unranking game" )
134+ ranked = False
135+ break
136+
137+ if ranked != game .ranked :
138+ logger .info (f"Laserball Game ID { game .id } ranked status changed from { game .ranked } to { ranked } " )
139+ game .ranked = ranked
140+ await game .save ()
141+
142+ # unranked -> ranked
143+
144+ if ranked :
145+ await ratinghelper .update_laserball_ratings (game )
146+
147+ return response .json ({"status" : "ok" })
0 commit comments