Skip to content

Instantly share code, notes, and snippets.

@gcampfield
Last active September 30, 2017 17:20
Show Gist options
  • Save gcampfield/be5b6e22744f6f1f34179e1ab233056e to your computer and use it in GitHub Desktop.
Save gcampfield/be5b6e22744f6f1f34179e1ab233056e to your computer and use it in GitHub Desktop.
A script to generate Dota pick/ban tables
import requests
# ---------- CONSTANTS ----------
OPTIC_ID = 5026801
RADIANT = 0
DIRE = 1
NONE = 2
SEP = '\n***\n'
heroes_url = 'https://www.trackdota.com/static/names.json'
heroes = requests.get(heroes_url).json().get('heroes')
hashes = {
'OpTic Gaming': '#optic',
'Immortals': '#immortals',
}
# ---------- UTILITIES ----------
def safe_get(l, i, default=None):
try:
return l[i]
except IndexError:
return default
def time_str(time):
if time is None:
return ''
if time < 0:
return '-'
minutes = time // 60
seconds = time % 60
return str(minutes) + ":" + str(seconds).zfill(2)
# ---------- GETTERS/SETTERS ----------
# data
def get_core_data(game_id):
core_url = 'https://www.trackdota.com/data/game/%s/core.json' % game_id
return requests.get(core_url).json()
def get_live_data(game_id):
live_url = 'https://www.trackdota.com/data/game/%s/live.json' % game_id
return requests.get(live_url).json()
# heroes
def get_hero(player):
hero_id = player.get('hero_id', 0)
if type(hero_id) != int:
hero_id = 0
player['hero_name'] = safe_get(heroes, hero_id, '<Unknown>')
def get_heroes(players):
for player in players:
get_hero(player)
return players
# pickbans
def get_pickbans(team, core_data):
side = team['side']
team['picks'] = get_heroes(core_data.get(side + '_picks', []))
team['bans'] = get_heroes(core_data.get(side + '_bans', []))
# stats
def get_player_stats(player, player_stats):
if 'account_id' not in player:
return
player_id = player['account_id']
for stats in player_stats:
if stats.get('account_id', 0) == player_id:
player['stats'] = stats
def get_stats(players, live_data):
get_heroes(players)
radiant_stats = live_data.get('radiant', {}).get('players', {})
dire_stats = live_data.get('dire', {}).get('players', {})
for player in players:
if 'team' not in player:
continue
if player['team'] == DIRE:
get_player_stats(player, dire_stats)
elif player['team'] == RADIANT:
get_player_stats(player, radiant_stats)
# events
def get_events(log):
barracks = {}
towers = {}
winner = None
for event in log:
if 'action' in event and 'delta' in event and 'timestamp' in event:
if event['action'] == 'barracks':
barracks[event['delta']] = event['timestamp']
elif event['action'] == 'tower':
towers[event['delta']] = event['timestamp']
elif event['action'] == 'win':
if event['delta'] == 0:
winner = ('radiant', event['timestamp'])
else:
winner = ('dire', event['timestamp'])
return barracks, towers, winner
RADIANT = 0
DIRE = 1
SIDE = 0
TIME = 1
def set_winner(optic, opp, winner):
if not winner: return
if winner[SIDE] == optic['side']:
optic['win_time'] = winner[TIME]
else:
opp['win_time'] = winner[TIME]
LANES = 3
TIERS = 4
def get_tower_index(side, lane, tier):
if tier == TIERS-1:
if lane == 1: return -1 # mid lane has no tier 4
return 9 + (side == 'dire') * 11 + (lane == 2)
offset = lane * 3 + tier
if side == 'radiant':
offset += 11
return offset
def get_barrack_index(side, lane, barrack):
offset = lane * 2 + barrack
if side == 'radiant':
offset += 6
return offset
def get_towers(towers):
radiant_towers = []
dire_towers = []
for tier in range(TIERS):
radiant_tier = []
dire_tier = []
for lane in range(LANES):
index = get_tower_index('radiant', lane, tier)
if index < 0: radiant_tier.append(index)
else: radiant_tier.append(towers.get(index, None))
index = get_tower_index('dire', lane, tier)
if index < 0: dire_tier.append(index)
else: dire_tier.append(towers.get(index, None))
radiant_towers.append(radiant_tier)
dire_towers.append(dire_tier)
return radiant_towers, dire_towers
BARRACKS = 2
def get_barracks(barracks):
radiant_barracks = []
dire_barracks = []
for barrack in range(BARRACKS):
radiant_tier = []
dire_tier = []
for lane in range(LANES):
index = get_barrack_index('radiant', lane, barrack)
radiant_tier.append(barracks.get(index, None))
index = get_barrack_index('dire', lane, barrack)
dire_tier.append(barracks.get(index, None))
radiant_barracks.append(radiant_tier)
dire_barracks.append(dire_tier)
return radiant_barracks, dire_barracks
# ---------- OUTPUT ----------
def it(s):
return '*' + str(s) + '*'
def bold(s):
return '**' + str(s) + '**'
def strike(s):
return '~~' + str(s) + '~~'
# pickbans
def print_pickban_header(optic, opp):
dire, radiant = '[](#dire) Dire', '[](#radiant) Radiant'
if optic['side'] == 'radiant':
a, b = radiant, dire
else:
a, b = dire, radiant
top_line = "%s|[%s](%s)|vs|[%s](%s)|%s\n" % \
(a, optic['team_name'], optic['hash'], opp['team_name'], opp['hash'], b)
print(top_line + \
":--|:--|:-:|--:|--:\n" + \
"**Bans**|**Picks**|**#**|**Picks**|**Bans**")
def print_pickban_line(row, p1, b1, p2, b2):
info = []
info.append(strike(b1['hero_name']))
info.append(p1['hero_name'])
info.append(bold(row))
info.append(p2['hero_name'])
info.append(strike(b2['hero_name']))
print('|'.join(info))
def print_pickban_table(optic, opp):
print_pickban_header(optic, opp)
row = 1
data = zip(optic['picks'], optic['bans'], opp['picks'], optic['bans'])
for og_p, og_b, opp_p, opp_b in data:
print_pickban_line(row, og_p, og_b, opp_p, opp_b)
row += 1
# stats
def print_stats_header():
print("Hero|Player|K/D/A|LH/D| # |LH/D|K/D/A|Player|Hero\n" + \
":---|:-----|:---:|:--:|:-:|:--:|:---:|-----:|---:")
def kda(player):
stats = player['stats']
return '%s/%s/%s' % (stats['kills'], stats['death'], stats['assists'])
def lhd(player):
stats = player['stats']
return '%s/%s' % (stats['last_hits'], stats['denies'])
def print_stats_line(og_player, opp_player, row):
info = []
info.append(og_player['hero_name'])
info.append(bold(og_player['name']))
info.append(kda(og_player))
info.append(lhd(og_player))
info.append(bold(row))
info.append(lhd(opp_player))
info.append(kda(opp_player))
info.append(bold(opp_player['name']))
info.append(opp_player['hero_name'])
print('|'.join(info))
def print_stats_table(optic, opp):
print_stats_header()
row = 1
data = zip(optic['players'], opp['players'])
for og_player, opp_player in data:
print_stats_line(og_player, opp_player, row)
row += 1
# events
def print_events_header(optic, opp):
top_line = "[%s](%s)|Top|Middle|Bottom||Bottom|Middle|Top|[%s](%s)\n" % \
(optic['team_name'], optic['hash'], opp['team_name'], opp['hash'])
print(top_line + \
":-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:")
buildings = ['T1', 'T2', 'T3', 'Melee', 'Ranged', 'T4']
def print_event_line(og_buildings, opp_buildings, row):
info = []
info.append(bold(buildings[row]))
for building in og_buildings:
info.append(time_str(building))
info.append('')
for building in opp_buildings:
info.append(time_str(building))
info.append(bold(buildings[row]))
print('|'.join(info))
def print_winner_line(optic, opp):
info = []
info.append(bold('Ancient'))
info.append('-')
info.append(time_str(optic.get('win_time', None)))
info.append('-')
info.append('')
info.append('-')
info.append(time_str(opp.get('win_time', None)))
info.append('-')
info.append(bold('Ancient'))
print('|'.join(info))
def print_events_table(optic, opp):
print_events_header(optic, opp)
row = 0
data = zip(optic['towers'][:-1], opp['towers'][:-1])
for og_towers, opp_towers in data:
print_event_line(og_towers, reversed(opp_towers), row)
row += 1
data = zip(optic['barracks'], opp['barracks'])
for og_barracks, opp_barracks in data:
print_event_line(og_barracks, reversed(opp_barracks), row)
row += 1
print_event_line(optic['towers'][-1], opp['towers'][-1], row)
print_winner_line(optic, opp)
# ---------- MAIN ----------
if __name__ == '__main__':
# game_id = int(input('dota game id: '))
game_id = 3475184410
core_data = get_core_data(game_id)
live_data = get_live_data(game_id)
radiant_team = core_data.get('radiant_team', {})
dire_team = core_data.get('dire_team', {})
if 'team_name' not in radiant_team:
radiant_team['team_name'] = 'Radiant'
if 'team_name' not in dire_team:
dire_team['team_name'] = 'Dire'
players = core_data.get('players', [])
radiant_players = filter(lambda p: p.get('team', NONE) == RADIANT, players)
dire_players = filter(lambda p: p.get('team', NONE) == DIRE, players)
get_stats(radiant_players, live_data)
get_stats(dire_players, live_data)
log = live_data.get('log', [])
barracks, towers, winner = get_events(log)
radiant_towers, dire_towers = get_towers(towers)
radiant_barracks, dire_barracks = get_barracks(barracks)
if radiant_team.get('team_id', 0):# == OPTIC_ID:
optic = radiant_team
opp = dire_team
opp['players'] = dire_players
opp['side'] = 'dire'
optic['players'] = radiant_players
optic['towers'] = dire_towers
optic['barracks'] = dire_barracks
opp['towers'] = radiant_towers
opp['barracks'] = radiant_barracks
optic['side'] = 'radiant'
elif dire_team.get('team_id', 0) == OPTIC_ID:
optic = dire_team
opp = radiant_team
opp['players'] = radiant_players
opp['side'] = 'radiant'
optic['players'] = dire_players
optic['towers'] = radiant_towers
optic['barracks'] = radiant_barracks
opp['towers'] = dire_towers
opp['barracks'] = dire_barracks
optic['side'] = 'dire'
else:
print('OpTic can\'t be detected in this match...')
exit(1)
optic['team_name'] = 'OpTic Gaming'
get_pickbans(optic, core_data)
get_pickbans(opp, core_data)
opp['hash'] = hashes.get(opp.get('team_name', ''), '#blank')
optic['hash'] = '#optic'
set_winner(optic, opp, winner)
print_pickban_table(optic, opp)
print(SEP)
print_stats_table(optic, opp)
print(SEP)
print_events_table(optic, opp)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment