Skip to content

Instantly share code, notes, and snippets.

@szarroug3
Last active September 12, 2023 06:49
Show Gist options
  • Save szarroug3/e3cb6a8a77f765c28444c56c23698788 to your computer and use it in GitHub Desktop.
Save szarroug3/e3cb6a8a77f765c28444c56c23698788 to your computer and use it in GitHub Desktop.
import requests
import xlsxwriter
from argparse import ArgumentParser
from collections import defaultdict
from copy import copy
from datetime import datetime
from itertools import zip_longest
from time import sleep
from urllib.parse import urlencode
DOTA_BASE_URL = 'https://api.steampowered.com/IDOTA2Match_570/{{func_name}}/V1/?key={api_key}&{{params}}'
OPENDOTA_BASE_URL = 'https://api.opendota.com/api/{func_name}/{params}'
LANE_ROLE = {
1: ['1', '5'],
2: ['2'],
3: ['3', '4'],
4: ['J']
}
COLORS = ['yellow', 'orange', 'cyan', 'silver', '#FF7F50', '#FFD700', '#ADFF2F',
'#40E0D0', '#00BFFF', '#D8BFD8', '#FFC0CB', '#FAEBD7', '#E6E6FA', '#FFD700']
RANKS = {'1': 'Herald', '2': 'Guardian', '3': 'Crusader', '4': 'Archon',
'5': 'Legend', '6': 'Ancient', '7': 'Divine', '8': 'Immortal', 'N': 'Unranked'}
def dota_api_call(func_name, **params):
for retry in range(1, 6):
resp = requests.get(DOTA_BASE_URL.format(func_name=func_name, params=urlencode(params)))
if resp.ok:
break
sleep(20)
print('Retry #{}'.format(retry))
if not resp.ok:
raise Exception('Something went wrong: GET {}: {} {}'.format(func_name, resp.status_code, resp.reason))
return resp.json().get('result', {})
def opendota_api_call(func_name, *params):
for retry in range(1, 6):
resp = requests.get(OPENDOTA_BASE_URL.format(func_name=func_name, params='/'.join(params)))
if resp.ok:
break
sleep(20)
print('Retry #{}'.format(retry))
if not resp.ok:
raise Exception('Something went wrong: GET {}: {} {}'.format(func_name, resp.status_code, resp.reason))
return resp.json()
def get_heroes():
data = opendota_api_call('heroes')
return {hero['id']: hero['localized_name'] for hero in data}
def get_captains(match_id, side, player_names):
data = dota_api_call('GetMatchDetails', match_id=match_id)
captain_id = data.get('dire_captain') if side == 'dire' else data.get('radiant_captain')
enemy_captain_id = data.get('dire_captain') if side == 'radiant' else data.get('radiant_captain')
if captain_id:
captain_name = get_player_name(captain_id, player_names)
else:
captain_name = ''
if enemy_captain_id:
enemy_captain_name = get_player_name(enemy_captain_id, player_names)
else:
enemy_captain_name = ''
return captain_name, enemy_captain_name
def get_player_names(match, picks, player_names):
for player in match['players']:
hero_id = player['hero_id']
account_id = player['account_id']
if hero_id not in picks:
continue
picks[hero_id]['player_name'] = get_player_name(account_id, player_names)
return picks, player_names
def get_player_name(account_id, player_names):
account_id = str(account_id)
if account_id not in player_names:
data = opendota_api_call('players', account_id)
if 'profile' not in data:
return
player_names[account_id] = {'name': data['profile']['personaname']}
return player_names[account_id]['name']
def parse_match(match, heroes):
try:
data = opendota_api_call('matches', str(match))
except:
print('match {} could not be found using dotabuff api'.format(match))
return
if data.get('picks_bans'):
return ParsedMatch(data, heroes)
else:
return UnparsedMatch(data, heroes)
class Match(object):
def __init__(self, data, team_id, players):
self.data = data
self.team_id = team_id
self.match_id = data['match_id']
self.side = self.get_side(team_id, str(data['dire_team_id']))
self.win = self.get_win(data['radiant_win'])
self.picks = {}
self.player_lanes = defaultdict()
def get_side(self, team_id, dire_team_id):
if dire_team_id == team_id:
return 'dire'
return 'radiant'
def get_win(self, radiant_win):
if self.side == 'radiant' and radiant_win:
return True
if self.side == 'dire' and not radiant_win:
return True
return False
class ParsedMatch(Match):
def __init__(self, data, heroes, team_id=None, players={}):
Match.__init__(self, data, team_id, players)
self.team_side_number = 0 if self.side == 'radiant' else 1
self.first_pick = None
self.bans = {}
self.enemy_bans = {}
self.captain, self.enemy_captain = get_captains(self.match_id, self.side, players)
self.get_picks_bans(heroes)
self.get_support_indices()
self.get_player_info()
def get_picks_bans(self, heroes):
for picks_bans in self.data['picks_bans']:
# enemy pick, don't care
if picks_bans['team'] != self.team_side_number and picks_bans['is_pick']:
continue
if self.first_pick is None:
if picks_bans['team'] == self.team_side_number and picks_bans['is_pick']:
self.first_pick = picks_bans['order'] == 6
hero_id = picks_bans['hero_id']
hero_name = heroes[hero_id]
if picks_bans['is_pick']:
self.picks[hero_id] = {'name': hero_name, 'order': picks_bans['order']}
else:
if picks_bans['team'] == self.team_side_number:
self.bans[hero_id] = {'name': hero_name, 'order': picks_bans['order']}
else:
self.enemy_bans[hero_id] = {'name': hero_name, 'order': picks_bans['order']}
def get_support_indices(self):
support = {}
for player in self.data['players']:
if player['hero_id'] not in self.picks:
continue
support[player['account_id']] = 0
if not player['purchase']:
continue
for item, count in player['purchase'].items():
if item in ['ward_sentry', 'ward_observer', 'dust']:
support[player['account_id']] += count
self.support_indices = [account_id for account_id, count in sorted(support.items(), key=lambda item: item[1])]
def get_player_role(self, lane_role, support_index):
possibilities = LANE_ROLE.get(lane_role, ['?'])
if len(possibilities) == 1:
return possibilities[0]
if support_index > 2:
return possibilities[1]
return possibilities[0]
def get_player_info(self):
for player in self.data['players']:
hero_id = player['hero_id']
if hero_id not in self.picks:
continue
role = self.get_player_role(player.get('lane_role'), self.support_indices.index(player['account_id']))
self.picks[hero_id].update({'role': role,
'roaming': player.get('is_roaming', False)})
self.player_lanes[player['account_id']] = role
class UnparsedMatch(Match):
def __init__(self, data, heroes, team_id=None, players={}, account_ids=[]):
Match.__init__(self, data, team_id, players)
self.get_player_info(heroes, account_ids)
def get_player_info(self, heroes, account_ids):
for player in self.data['players']:
hero_id = player['hero_id']
if str(player['account_id']) not in account_ids:
continue
self.picks[hero_id] = ({'name': heroes[hero_id],
'roaming': player.get('is_roaming', False)})
class Player(object):
def __init__(self, account_id, player_names, heroes, teams):
self.account_id = account_id
self.name = get_player_name(self.account_id, player_names)
if not self.name:
raise Exception('Player profile could not be found.')
self.rank = self.get_rank()
self.heroes = self.get_heroes(heroes)
self.recent_heroes_count, self.recent_heroes_time = self.get_recent_heroes(heroes)
self.statistics = self.get_player_lane_statistics(teams)
def __str__(self):
return f'{self.account_id}: {self.name}'
def get_rank(self):
data = opendota_api_call('players', self.account_id)
rank_tier = str(data['rank_tier'])
medal = RANKS[rank_tier[0]]
if medal == 'Immortal':
stars = data['leaderboard_rank']
else:
stars = rank_tier[1]
if stars:
return '{} {}'.format(medal, stars)
return medal
def get_heroes(self, heroes):
data = opendota_api_call('players', self.account_id, 'heroes')
hero_data = []
for hero in sorted(data, key=lambda h: h['games'], reverse=True)[:5]:
hero_id = hero['hero_id']
if hero['games']:
win_rate = hero['win'] * 100 / hero['games']
# this can happen if the player has never played this hero before
else:
win_rate = 0
hero_data.append({'name': heroes[int(hero_id)], 'games': hero['games'],
'win_rate': '{:.1f}%'.format(win_rate)})
return hero_data
def get_recent_heroes(self, heroes, number_of_matches=40, months_of_matches=3):
data = opendota_api_call('players', self.account_id, 'matches')
today = datetime.utcnow().replace(minute=0, second=0, microsecond=0)
months_ago = today.replace(month=((today.month + 12 - months_of_matches) % 12))
epoch = datetime.utcfromtimestamp(0)
epoch_months_ago = (months_ago - epoch).total_seconds()
hero_data_number = defaultdict(lambda: defaultdict(int))
hero_data_months = defaultdict(lambda: defaultdict(int))
for index, match in enumerate(data):
if match['start_time'] < epoch_months_ago and index >= number_of_matches:
break
if match['start_time'] >= epoch_months_ago:
hero_id = match['hero_id']
name = heroes[hero_id]
hero_data_months[name]['count'] += 1
if match['player_slot'] > 100 and not match['radiant_win']:
hero_data_months[name]['wins'] += 1
if match['player_slot'] < 100 and match['radiant_win']:
hero_data_months[name]['wins'] += 1
if index <= number_of_matches:
hero_id = match['hero_id']
name = heroes[hero_id]
hero_data_number[name]['count'] += 1
if match['player_slot'] > 100 and not match['radiant_win']:
hero_data_number[name]['wins'] += 1
if match['player_slot'] < 100 and match['radiant_win']:
hero_data_number[name]['wins'] += 1
return hero_data_number, hero_data_months
def get_player_lane_statistics(self, teams):
lanes = defaultdict(int)
total = 0
for team in teams:
for lane, count in team.player_lanes[int(self.account_id)].items():
lanes[lane] += count
total += count
percentages = []
for lane, count in sorted(lanes.items(), key=lambda lane: lane[1], reverse=True):
percentages.append('{}: {:.0f}%'.format(lane, count * 100.0/total))
return ', '.join(percentages)
class Team(object):
def __init__(self, team_id, player_names, heroes, league_id, extra_match_ids=[], skip_match_ids=[]):
self.team_id = team_id
self.player_names = player_names
self.heroes = heroes
self.parsed_matches = []
self.unparsed_matches = []
self.pick_count = defaultdict(lambda: defaultdict(int))
self.ban_count = defaultdict(int)
self.enemy_bans_count = defaultdict(int)
self.players = []
self.get_team_data()
matches = self.get_team_matches(league_id=league_id)
matches = matches.union(extra_match_ids)
matches = [match for match in matches if match not in skip_match_ids]
self.parse_matches(matches)
self.get_player_lane_statistics()
def get_team_data(self):
data = dota_api_call('GetTeamInfoByTeamID', start_at_team_id=self.team_id, teams_requested=1)
if not data['teams']:
raise Exception('Team with ID {} not found.'.format(self.team_id))
self.name = data['teams'][0]['name']
for key, value in data['teams'][0].items():
if not key.startswith('player') or not key.endswith('account_id'):
continue
value = str(value)
self.players.append(value)
sleep(.5)
def get_team_matches(self, league_id):
matches = set()
for league in league_id:
while True:
if matches:
matches_min = min(matches) - 1
else:
matches_min = None
new_matches = self.get_matches(copy(matches), league_id=league, start_at_match_id=matches_min)
if len(matches) == len(new_matches):
break
matches = new_matches
return matches
def get_matches(self, matches, league_id, start_at_match_id=None):
params = {'matches_requested': 1000, 'league_id': league_id}
if start_at_match_id:
params['start_at_match_id'] = start_at_match_id
data = dota_api_call('GetMatchHistory', **params)
for match in data['matches']:
if int(self.team_id) in [match['dire_team_id'], match['radiant_team_id']]:
matches.add(match['match_id'])
return matches
def parse_matches(self, matches):
for match in sorted(set(matches), reverse=True):
try:
data = opendota_api_call('matches', str(match))
except:
print('match {} could not be found using dotabuff api'.format(match))
continue
if data.get('picks_bans'):
match_details = ParsedMatch(data, heroes=self.heroes, team_id=self.team_id, players=self.player_names)
for hero in match_details.picks.values():
self.pick_count[hero['name']]['count'] += 1
if match_details.win:
self.pick_count[hero['name']]['wins'] += 1
for hero in match_details.enemy_bans.values():
self.enemy_bans_count[hero['name']] += 1
for hero in match_details.bans.values():
self.ban_count[hero['name']] += 1
self.parsed_matches.append(match_details)
else:
match_details = UnparsedMatch(data, heroes=self.heroes, team_id=self.team_id, players=self.player_names, account_ids=self.players)
self.unparsed_matches.append(match_details)
for hero in match_details.picks.values():
self.pick_count[hero['name']]['count'] += 1
if match_details.win:
self.pick_count[hero['name']]['wins'] += 1
def get_player_lane_statistics(self):
self.player_lanes = defaultdict(lambda: defaultdict(int))
for match in self.parsed_matches:
for account_id, lane in match.player_lanes.items():
self.player_lanes[account_id][lane] += 1
for match in self.unparsed_matches:
for account_id, lane in match.player_lanes.items():
self.player_lanes[account_id][lane] += 1
class XlsxWriter(object):
def __init__(self, file):
self.workbook = xlsxwriter.Workbook(file)
self.worksheet = self.workbook.add_worksheet()
self.colors = self.create_colors()
self.used_colors = set()
self.row = 0
def close(self):
self.workbook.close()
def create_colors(self):
colors = {}
for num, color in enumerate(COLORS, start=2):
colors[num] = self.workbook.add_format({'bg_color': color, 'border': 0})
return colors
def write_team_matches(self, team):
if not team.parsed_matches and not team.unparsed_matches:
return
if team.parsed_matches:
dotabuff_url = 'https://www.dotabuff.com/esports/teams/{}'.format(team.team_id)
self.worksheet.write_url(self.row, 0, dotabuff_url, None, team.name)
self.row += 1
self.write_parsed_matches_header()
self.write_parsed_matches(team.parsed_matches, team=team)
if team.unparsed_matches:
self.write_unparsed_matches_header()
self.write_unparsed_matches(team.unparsed_matches, team=team)
def write_matches(self, parsed_matches, unparsed_matches):
if not parsed_matches and not unparsed_matches:
return
if parsed_matches:
self.write_parsed_matches_header()
self.write_parsed_matches(parsed_matches)
if unparsed_matches:
self.write_unparsed_matches_header()
self.write_unparsed_matches(unparsed_matches)
def write_parsed_matches_header(self):
self.worksheet.write(self.row, 0, 'CAPTAIN')
self.worksheet.write(self.row, 1, 'PICKS')
self.worksheet.write(self.row, 6, 'PICK')
self.worksheet.write(self.row, 7, 'RESULT')
self.worksheet.write(self.row, 8, 'SIDE')
self.worksheet.write(self.row, 9, 'ENEMY CAPTAIN')
self.worksheet.write(self.row, 10, 'ENEMY BANS')
self.worksheet.write(self.row, 18, 'BANS')
self.row += 1
def write_parsed_matches(self, matches, team=None):
for match in matches:
self.write_parsed_match(match, team)
self.row += 1
self.row += 1
def write_parsed_match(self, match, team):
self.worksheet.write(self.row, 0, match.captain)
for column, pick in enumerate(sorted(match.picks.values(), key=lambda p: p['order']), start=1):
count = team.pick_count[pick['name']]['count'] if team else 1
color = self.colors.get(count)
self.used_colors.add(count)
self.write_hero(column, color=color, **pick)
self.worksheet.write(self.row, 6, 'FP' if match.first_pick else 'SP')
dotabuff_url = 'http://www.opendota.com/matches/{}'.format(match.match_id)
self.worksheet.write_url(self.row, 7, dotabuff_url, None, 'W' if match.win else 'L')
self.worksheet.write(self.row, 8, match.side)
self.worksheet.write(self.row, 9, match.enemy_captain)
for column, ban in enumerate(sorted(match.enemy_bans.values(), key=lambda p: p['order']), start=10):
count = team.enemy_bans_count[ban['name']] if team else 1
color = self.colors.get(count)
self.used_colors.add(count)
self.write_hero(column, color=color, **ban)
for column, ban in enumerate(sorted(match.bans.values(), key=lambda p: p['order']), start=18):
count = team.ban_count[ban['name']] if team else 1
color = self.colors.get(count)
self.used_colors.add(count)
self.write_hero(column, color=color, **ban)
def write_unparsed_matches_header(self):
self.worksheet.write(self.row, 0, 'PICKS')
self.worksheet.write(self.row, 5, 'RESULT')
self.worksheet.write(self.row, 6, 'SIDE')
self.row += 1
def write_unparsed_matches(self, matches, team=None):
for match in matches:
self.write_unparsed_match(match, team)
self.row += 1
self.row += 1
def write_unparsed_match(self, match, team):
for column, pick in enumerate(sorted(match.picks.values(), key=lambda p: p['name'])):
count = team.pick_count[pick['name']]['count'] if team else 1
color = self.colors.get(count)
self.used_colors.add(count)
self.write_hero(column, color=color, **pick)
dotabuff_url = 'http://www.opendota.com/matches/{}'.format(match.match_id)
self.worksheet.write_url(self.row, 5, dotabuff_url, None, 'W' if match.win else 'L')
self.worksheet.write(self.row, 6, match.side)
def write_summary(self, team):
self.worksheet.write(self.row, 0, 'SUMMARY')
self.row += 1
self.worksheet.write(self.row, 0, 'PICK')
self.worksheet.write(self.row, 1, 'COUNT')
self.worksheet.write(self.row, 2, 'WINS')
self.worksheet.write(self.row, 3, 'WIN RATE')
self.worksheet.write(self.row, 5, 'ENEMY BANS')
self.worksheet.write(self.row, 6, 'COUNT')
self.worksheet.write(self.row, 8, 'BAN')
self.worksheet.write(self.row, 9, 'COUNT')
self.row += 1
pick_row, enemy_bans_row, ban_row = self.row, self.row, self.row
pick_count = sorted(team.pick_count.items(), key=lambda p: (-p[1]['count'], p[0]))
enemy_bans_count = sorted(team.enemy_bans_count.items(), key=lambda b: b[1], reverse=True)
ban_count = sorted(team.ban_count.items(), key=lambda b: b[1], reverse=True)
for pick, enemy_bans, ban in zip_longest(pick_count, enemy_bans_count, ban_count):
if pick:
win_rate = '{:.1f}%'.format(pick[1]['wins'] * 100 / pick[1]['count'])
if pick[1]['wins'] == pick[1]['count']:
self.worksheet.write(pick_row, 0, pick[0], self.colors[2])
self.worksheet.write(pick_row, 1, pick[1]['count'], self.colors[2])
self.worksheet.write(pick_row, 2, pick[1]['wins'], self.colors[2])
self.worksheet.write(pick_row, 3, win_rate, self.colors[2])
else:
self.worksheet.write(pick_row, 0, pick[0])
self.worksheet.write(pick_row, 1, pick[1]['count'])
self.worksheet.write(pick_row, 2, pick[1]['wins'])
self.worksheet.write(pick_row, 3, win_rate)
pick_row += 1
if enemy_bans:
self.worksheet.write(enemy_bans_row, 5, enemy_bans[0])
self.worksheet.write(enemy_bans_row, 6, enemy_bans[1])
enemy_bans_row += 1
if ban:
self.worksheet.write(ban_row, 8, ban[0])
self.worksheet.write(ban_row, 9, ban[1])
ban_row += 1
self.row = max(pick_row, enemy_bans_row, ban_row)
self.row += 1
def write_hero(self, column, color=None, name=None, role=None, roaming=False, **kwargs):
data = name
if role:
data += ' ' + role
if roaming:
data += ' (R)'
if color:
self.worksheet.write(self.row, column, data, color)
else:
self.worksheet.write(self.row, column, data)
def write_legend(self):
if not self.used_colors:
return
self.worksheet.write(self.row, 0, 'LEGEND')
self.row += 1
for column, count in enumerate(sorted(self.used_colors)):
color = self.colors.get(count)
if count == len(COLORS):
count = '{}+'.format(count)
if color:
self.worksheet.write(self.row, column, count, color)
else:
self.worksheet.write(self.row, column, count)
self.row += 2
def write_players(self, players, highlight_heroes, player_order=[], input_players=[]):
if not players:
return
self.worksheet.write(self.row, 0, 'PLAYERS')
self.row += 1
bold = self.workbook.add_format({'bold': True})
starting_row = self.row
column = 0
sorted_players = []
# first order by given order
for account_id in player_order:
for player in players:
if player.account_id == account_id:
sorted_players.append(player)
break
# then order by alphabetical names
for player in sorted(players, key=lambda p: p.name.lower()):
if player.account_id not in player_order:
sorted_players.append(player)
for player in sorted_players:
# this will filter out players who have been on this team before but never
# played in one of the matches on the sheet except for players who were
# specified in the input args
if not player.statistics and player.account_id not in input_players:
continue
dotabuff_url = 'https://www.opendota.com/players/{}'.format(player.account_id)
self.worksheet.write_url(self.row, column, dotabuff_url, None, player.name)
self.worksheet.write(self.row, column+1, player.rank, bold)
self.worksheet.write(self.row, column+2, player.statistics)
self.row += 1
self.worksheet.write(self.row, column, 'HERO')
self.worksheet.write(self.row, column+1, 'GAMES')
self.worksheet.write(self.row, column+2, 'WIN RATE')
self.row += 1
for hero in player.heroes:
if hero['name'].lower() in highlight_heroes:
self.worksheet.write(self.row, column, hero['name'], self.colors[2])
self.worksheet.write(self.row, column+1, hero['games'], self.colors[2])
self.worksheet.write(self.row, column+2, hero['win_rate'], self.colors[2])
else:
self.worksheet.write(self.row, column, hero['name'])
self.worksheet.write(self.row, column+1, hero['games'])
self.worksheet.write(self.row, column+2, hero['win_rate'])
self.row += 1
self.row += 1
self.worksheet.write(self.row, column, 'HERO')
self.worksheet.write(self.row, column+1, 'RECENT GAMES')
self.worksheet.write(self.row, column+2, 'RECENT WIN RATE')
self.row += 1
for hero, data in sorted(player.recent_heroes_count.items(), key=lambda h: h[1]['count'], reverse=True):
win_rate = '{:.1f}%'.format(data['wins'] * 100 / data['count'])
if hero.lower() in highlight_heroes:
self.worksheet.write(self.row, column, hero, self.colors[2])
self.worksheet.write(self.row, column+1, data['count'], self.colors[2])
self.worksheet.write(self.row, column+2, win_rate, self.colors[2])
else:
self.worksheet.write(self.row, column, hero)
self.worksheet.write(self.row, column+1, data['count'])
self.worksheet.write(self.row, column+2, win_rate)
self.row += 1
self.row +=1
# self.worksheet.write(self.row, column, 'HERO')
# self.worksheet.write(self.row, column+1, 'RECENT GAMES')
# self.worksheet.write(self.row, column+2, 'RECENT WIN RATE')
# self.row += 1
# for hero, data in sorted(player.recent_heroes_time.items(), key=lambda h: h[1]['count'], reverse=True):
# win_rate = '{:.1f}%'.format(data['wins'] * 100 / data['count'])
# if hero.lower() in highlight_heroes:
# self.worksheet.write(self.row, column, hero, self.colors[2])
# self.worksheet.write(self.row, column+1, data['count'], self.colors[2])
# self.worksheet.write(self.row, column+2, win_rate, self.colors[2])
# else:
# self.worksheet.write(self.row, column, hero)
# self.worksheet.write(self.row, column+1, data['count'])
# self.worksheet.write(self.row, column+2, win_rate)
# self.row += 1
self.row = starting_row
column += 4
self.row += 1
def get_args():
parser = ArgumentParser()
parser.add_argument('api_key', help='steam api key -- you can get a key from https://steamcommunity.com/dev/apikey')
parser.add_argument('-l', '--league-id', action='append', default=[], help='(required for team scouting only) the league to use for teams -- you can get this from dotabuff')
parser.add_argument('-t', '--team-id', action='append', default=[], help='(optional -- supports multiples) teams to scout -- you can get this from dotabuff')
parser.add_argument('-p', '--player', action='append', default=[], help='(optional -- supports multiples) players to scout -- you can get this from dotabuff')
parser.add_argument('-m', '--match', action='append', default=[], type=int, help='(optional -- supports multiples) extra matches to parse -- you can get this from dotabuff')
parser.add_argument('-s', '--skip-match', action='append', default=[], type=int, help='(optional -- supports multiples) matches to skip -- you can get this from dotabuff')
parser.add_argument('-c', '--counterpick-heroes', help='(optional) file of heroes to highlight if found in recent matches; file should be comma separated')
parser.add_argument('-o', '--ordered-players', action='store_true', help='print player information in the order players were given')
parser.add_argument('-f', '--file', help='the file to save results to')
return parser.parse_args()
def process(api_key, league_id=[], team_id=[], player=[], match=[], skip_match=[], counterpick_heroes=None, ordered_players=False, file=None):
global DOTA_BASE_URL
DOTA_BASE_URL = DOTA_BASE_URL.format(api_key=api_key)
current_time = datetime.utcnow().strftime('%Y%m%d%H%M%S')
file = file if file else '{}.xlsx'.format(current_time)
player_names = {}
players = {}
player_ids = set(player)
heroes = get_heroes()
highlight_heroes = []
if counterpick_heroes:
with open(counterpick_heroes) as f:
lowered_hero_names = [h.lower() for h in heroes.values()]
for hero in f.read().split(','):
filtered_hero = hero.strip().lower()
if filtered_hero not in lowered_hero_names:
print('Warning: {} not a valid hero name and will be ignored'.format(hero))
continue
highlight_heroes.append(filtered_hero)
try:
writer = XlsxWriter(file)
teams = []
if team_id:
for tid in team_id:
team = Team(tid, player_names, heroes, league_id=league_id, extra_match_ids=match, skip_match_ids=skip_match)
teams.append(team)
player_ids.update(team.players)
writer.write_team_matches(team)
writer.write_legend()
writer.write_summary(team)
elif match:
parsed_matches = []
unparsed_matches = []
for m in sorted(match):
if m in skip_match:
continue
match_data = parse_match(m, heroes)
if isinstance(match_data, ParsedMatch):
parsed_matches.append(match_data)
else:
unparsed_matches.append(match_data)
writer.write_matches(parsed_matches, unparsed_matches)
for player_id in player_ids:
try:
players[player_id] = Player(player_id, player_names, heroes, teams)
except Exception as e:
print('Skipping player with ID {}. Player profile may be private. Error: {}'.format(player_id, e))
writer.write_players(players.values(), highlight_heroes, player_order=player if ordered_players else [], input_players=player)
writer.close()
except Exception as e:
import traceback
traceback.print_exc()
if __name__ == '__main__':
process(**vars(get_args()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment