Skip to content

Commit bdb9fea

Browse files
committed
Moving to AoE4World for some data
1 parent 8112f3d commit bdb9fea

File tree

4 files changed

+84
-153
lines changed

4 files changed

+84
-153
lines changed

src/AoE4_Overlay.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
logger = get_logger(__name__)
1818

19-
VERSION = "1.2.7"
19+
VERSION = "1.2.8"
2020

2121
# Might or might not help
2222
os.environ["PYTHONIOENCODING"] = "utf-8"

src/overlay/api_checking.py

Lines changed: 39 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import json
1717
import time
18+
from datetime import datetime
1819
from typing import Any, Dict, List, Optional, Tuple
1920

2021
import requests
@@ -249,13 +250,13 @@ class Api_checker:
249250

250251
def __init__(self):
251252
self.force_stop = False
252-
self.last_match_timestamp = -1
253-
self.last_rating_timestamp = -1
253+
self.last_match_timestamp = datetime(1900, 1, 1, 0, 0, 0)
254+
self.last_rating_timestamp = datetime(1900, 1, 1, 0, 0, 0)
254255

255256
def reset(self):
256257
""" Resets last timestamps"""
257-
self.last_match_timestamp = -1
258-
self.last_rating_timestamp = -1
258+
self.last_match_timestamp = datetime(1900, 1, 1, 0, 0, 0)
259+
self.last_rating_timestamp = datetime(1900, 1, 1, 0, 0, 0)
259260

260261
def sleep(self, seconds: int) -> bool:
261262
""" Sleeps while checking for force_stop
@@ -284,133 +285,56 @@ def check_for_new_game(self,
284285
return
285286

286287
def get_data(self) -> Optional[Dict[str, Any]]:
287-
""" Returns match data if there is a new game"""
288288
if self.force_stop:
289289
return
290290

291-
# Match history
291+
# Get last match from aoe4world.com
292292
try:
293-
match_history = get_match_history(amount=1, raise_exception=True)
294-
except json.decoder.JSONDecodeError:
295-
# AoEIV.net down
296-
return {'server_down': True}
293+
url = f"https://aoe4world.com/api/v0/players/{settings.profile_id}/games/last"
294+
resp = session.get(url)
295+
data = json.loads(resp.text)
297296
except Exception:
298-
return
299-
300-
if not match_history:
301-
return
302-
303-
match = match_history[0]
304-
leaderboard_id = match_mode(match)
305-
306-
# No players in the game
307-
if not match['players']:
297+
logger.exception("")
308298
return
309299

310300
if self.force_stop:
311301
return
312-
313-
# Show the last game
314-
if match['started'] > self.last_match_timestamp:
315-
self.last_match_timestamp = match['started']
316-
317-
# Remove duplicated players
318-
match['players'] = self.get_unique_players(match['players'])
319-
# Gets additional player data from leaderboards stats (in-place)
320-
for player in match['players']:
321-
self.get_player_data(leaderboard_id, player)
322-
return match
323-
324-
# Rating history
325-
if not quickmatch_game(match):
326-
return
327-
rating_history = get_rating_history(leaderboard_id, amount=1)
328-
if not rating_history:
302+
if "error" in data:
329303
return
330-
rating = rating_history[0]
331-
332-
# Check for new rating data
333-
if self.last_match_timestamp != -1 and \
334-
rating['timestamp'] > self.last_rating_timestamp:
335304

336-
self.last_rating_timestamp = rating['timestamp']
337-
return {"new_rating": True, 'timestamp': rating['timestamp']}
305+
# Calc old leaderboard id
306+
data['leaderboard_id'] = 0
307+
try:
308+
data['leaderboard_id'] = int(data['kind'][-1]) + 16
309+
except Exception:
310+
logger.exception("")
338311

339-
@staticmethod
340-
def get_unique_players(
341-
players: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
342-
""" Create a new list of players that has only unique players
312+
# Calc started time
313+
started = datetime.strptime(data['started_at'],
314+
"%Y-%m-%dT%H:%M:%S.000Z")
315+
data['started_sec'] = started.timestamp()
343316

344-
AoEIV.net sometimes returns players multiple times in player list """
345-
ids = set()
346-
filtered = list()
317+
# Show the last game
318+
if started > self.last_match_timestamp: # and data['ongoing']:
319+
self.last_match_timestamp = started
320+
return data
347321

348-
for p in players:
349-
playerid = p["profile_id"]
350-
if playerid in ids:
351-
continue
352-
ids.add(playerid)
353-
filtered.append(p)
354-
return filtered
322+
if not "qm_" in data['kind']:
323+
return
355324

356-
@staticmethod
357-
def get_player_data(leaderboard_id: int, player_dict: Dict[str, Any]):
358-
""" Updates player data inplace"""
325+
# When a game finished
326+
if started > self.last_rating_timestamp and not data['ongoing']:
359327

360-
try:
361-
url = f"https://aoe4world.com/api/v0/players/{player_dict['profile_id']}"
362-
data = json.loads(session.get(url).text)
363-
player_dict['name'] = data['name']
364-
365-
data = data['modes'][f'qm_{mode_data[leaderboard_id]}']
366-
player_dict['rank'] = zeroed(data["rank"])
367-
player_dict['rating'] = zeroed(data["rating"])
368-
player_dict['wins'] = zeroed(data["wins_count"])
369-
player_dict['losses'] = zeroed(data["games_count"]) - zeroed(
370-
data["wins_count"])
371-
player_dict['streak'] = zeroed(data["streak"])
372-
373-
# AoE4World.com civ stats currently work only for 1v1
374-
if mode_data[leaderboard_id] == "1v1":
375-
civ_name = net_to_world.get(player_dict['civ'])
376-
for civ in data['civilizations']:
377-
if civ['civilization'] == civ_name:
378-
player_dict['civ_games'] = civ['games_count']
379-
player_dict['civ_winrate'] = civ['win_rate']
380-
player_dict['civ_win_length_median'] = civ[
381-
'game_length']['wins_median']
382-
return
383-
logger.warning(
384-
f"Didn't find civ: {civ_name} in aoe4world.com player civ list"
385-
)
386-
return
387-
except Exception:
388-
logger.exception(
389-
f"AoE4wWorld.com failed for player {player_dict.get('profile_id')}"
390-
)
328+
# Check for new ratings
329+
if not data['leaderboard_id']:
330+
return
391331

392-
# If AoE4World.com fails, default to aoeiv.net
393-
try:
394-
url = f"https://aoeiv.net/api/leaderboard?game=aoe4&leaderboard_id={leaderboard_id}&profile_id={player_dict['profile_id']}&count=1"
395-
data = json.loads(session.get(url).text)
396-
397-
if data['leaderboard']:
398-
data = data["leaderboard"][0]
399-
player_dict['rank'] = data["rank"]
400-
player_dict['rating'] = data["rating"]
401-
player_dict['wins'] = data["wins"]
402-
player_dict['losses'] = data["losses"]
403-
player_dict['streak'] = data["streak"]
404-
405-
# Sometimes AoEIV.net returns no name for the player
406-
if player_dict['name'] is None:
407-
player_dict['name'] = data['name']
408-
else:
409-
player_dict['rating'] = "–"
332+
rating_history = get_rating_history(data['leaderboard_id'],
333+
amount=1)
410334

411-
except Exception:
412-
logger.exception("Failed to get player data from aoeiv.net")
335+
if not rating_history:
336+
return
413337

414-
# Last check on AoE4World for player name
415-
if player_dict['name'] is None:
416-
player_dict['name'] = get_player_name(player_dict['profile_id'])
338+
self.last_rating_timestamp = started
339+
rating = rating_history[0]
340+
return {"new_rating": True, 'timestamp': rating['timestamp']}

src/overlay/helper_func.py

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -91,55 +91,64 @@ def process_game(game_data: Dict[str, Any]) -> Dict[str, Any]:
9191
Sorts players to main is at the top. Calculates winrates.
9292
Gets text for civs and maps. Apart from `team`, all player data returned as string."""
9393
result = {}
94-
result['map'] = map_data.get(game_data["map_type"], "Unknown map")
95-
result['mode'] = match_mode(game_data)
96-
result['started'] = game_data['started']
97-
result['ranked'] = game_data['ranked']
94+
result['map'] = game_data['map']
95+
result['mode'] = game_data['leaderboard_id']
96+
result['started'] = game_data['started_at']
97+
result['ranked'] = 'qm_' in game_data['kind']
9898
result['server'] = game_data['server']
99-
result['version'] = game_data['version']
100-
result['match_id'] = game_data['match_id']
99+
result['match_id'] = game_data['game_id']
100+
mode = game_data['kind']
101101

102102
# Sort players so the main player team is first
103-
team = None
104-
for player in game_data['players']:
105-
if player['profile_id'] == settings.profile_id:
106-
team = player['team']
107-
break
103+
players = []
104+
main_team = None
105+
for idx, team in enumerate(game_data['teams']):
106+
for player in team:
107+
player['team'] = idx
108+
players.append(player)
109+
if player['profile_id'] == settings.profile_id:
110+
main_team = idx
108111

109112
def sortingf(player: Dict[str, Any]) -> int:
110113
if player['team'] is None:
111114
return 99
112-
if player['team'] == team:
115+
if player['team'] == main_team:
113116
return -1
114117
return player['team']
115118

116-
game_data['players'] = sorted(game_data['players'], key=sortingf)
119+
players = sorted(players, key=sortingf)
117120

118121
# Add player data
119122
result['players'] = []
120-
for player in game_data['players']:
121-
wins = zeroed(player.get('wins'))
122-
losses = zeroed(player.get('losses'))
123-
games = wins + losses
124-
winrate = wins / games if games else 0
125-
civ_win_median = ''
126-
if 'civ_win_length_median' in player:
127-
civ_win_median = time.strftime(
128-
"%M:%S", time.gmtime(player['civ_win_length_median']))
129-
civ_winrate = ''
130-
if 'civ_winrate' in player:
131-
civ_winrate = f"{player['civ_winrate']/100:.1%}"
123+
for player in players:
124+
current_civ = player['civilization']
125+
name = player['name'] if player['name'] is not None else "?"
126+
127+
civ_games = ""
128+
civ_winrate = ""
129+
civ_win_median = ""
130+
try:
131+
for civ in player['modes'][mode]['civilizations']:
132+
if civ['civilization'] == current_civ:
133+
civ_games = str(civ['games_count'])
134+
civ_winrate = f"{civ['win_rate']/100:.1%}"
135+
med = civ['game_length']['wins_median']
136+
civ_win_median = time.strftime("%M:%S", time.gmtime(med))
137+
except Exception:
138+
...
139+
140+
mode_data = player.get('modes', {}).get(mode, {})
132141

133142
data = {
134-
'civ': civ_data.get(player['civ'], "Unknown civ"),
135-
'name': player['name'],
136-
'team': zeroed(player['team']),
137-
'rating': str(player.get('rating', '')),
138-
'rank': f"#{player.get('rank', '')}",
139-
'wins': str(wins) if wins else '',
140-
'losses': str(losses) if losses else '',
141-
'winrate': f"{winrate:.1%}",
142-
'civ_games': str(player.get('civ_games', '')),
143+
'civ': current_civ.replace("_", " ").title(),
144+
'name': name,
145+
'team': zeroed(player['team'] + 1),
146+
'rating': str(mode_data.get('rating', 0)),
147+
'rank': f"#{mode_data.get('rank',0)}",
148+
'wins': str(mode_data.get('wins_count', 0)),
149+
'losses': str(mode_data.get('losses_count', 0)),
150+
'winrate': f"{mode_data.get('winrate',0)}%",
151+
'civ_games': civ_games,
143152
'civ_winrate': civ_winrate,
144153
'civ_win_length_median': civ_win_median
145154
}

src/overlay/tab_main.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,8 @@ def new_game(self, game_data: Optional[Dict[str, Any]]):
116116
if settings.log_matches:
117117
log_match(game_data)
118118
processed = hf.process_game(game_data)
119-
start = time.strftime("%Y-%m-%d %H:%M:%S",
120-
time.localtime(processed['started']))
121119
logger.info(
122-
f"New live game (match_id: {processed['match_id']} | mode: {processed['mode']-16} | started: {start})"
120+
f"New live game (game_id: {game_data['game_id']} | mode: {game_data['kind']} | started: {game_data['started_at']})"
123121
)
124122
self.override_tab.update_data(processed)
125123
if not self.prevent_overlay_update:

0 commit comments

Comments
 (0)