Pulls Smite matches from Smite API

Uses smite-python API wrapper by Jayden Bailey https://github.com/jaydenkieran/smite-python/blob/master/smite.py

Edit main method before running all cells. Check comments in main method for more.


In [1]:
import json
import os, sys
from smite import SmiteClient, NoResultError # in working directory
from datetime import datetime, timedelta
import pandas as pd
import pickle

In [2]:
def writefile(filename, data):
    with open(filename, 'w') as fout:
        json.dump(data, fout)

def readfile(filename):
    with open(filename, 'r') as fout:
        return json.load(fout)

In [4]:
def get_all_items(smite):
    # TODO update to be similar to get_all_gods.
    # DANGER # I have manually put in total item cost and haven't yet coded a way to do that,
    # Updating SMITE_Items_All_Lookup.csv will remove that column and break SmiteRecommender
    writefile('SMITE_Items_All.json', smite.get_items())
    print("Successfully updated Items_All file. Remember to manually update items lookup file")

def get_all_gods(smite):
    # Updates god info from SMITE API and creates lookup file
    god_info = smite.get_gods()
    writefile('SMITE_data/SMITE_Gods_All.json', god_info)
    all_gods = pd.DataFrame(god_info)
    lookup = all_gods.loc[:,["Name", 'Pantheon', 'Roles', 'Title', 'Type', 'id', 'godCard_URL', 'godIcon_URL',
                             'godAbility1_URL', 'godAbility2_URL', 'godAbility3_URL', 'godAbility4_URL', 'godAbility5_URL']]
    all_gods.to_csv("SMITE_data/SMITE_Gods_All.csv", index=None)
    lookup.to_csv("SMITE_data/SMITE_Gods_All_Lookup.csv", index=None)
    print("Successfully updated God lookup file")
    
def get_IDs(smite, date, game_mode=451, hour=-1):
    """ Gets match_ids by date and gamemode from SMITE API.
        returns output of check_IDs, a list of valid match ids
    Gamemodes:
    451 -ConquestLeague (ranked)
    426 -Conquest       (casual)
    440 -Ranked Duel (1v1 joust map)
    450 -Joust Ranked (3v3)   
    date example :20160423     
    hour=-1 (or 24) all day, or hour=0-23 
    """
    return(check_IDs(smite.get_match_ids_by_queue(game_mode, date, hour)))   

def check_IDs(ids):
    """ returns list of valid match ids """
    match_ids = []
    for match in ids:
        if match['Active_Flag'] == 'n':
            match_ids.append(match['Match'])
    print("Number of failed IDs: {}".format(len(ids)-len(match_ids)))
    return(match_ids)

def get_all_match_IDs(smite, start_date, stop_date, game_mode):
    """Get all match IDs for a specific game mode between two dates
        date example :20160423
        Returns a list of lists, one for each day
    """
    all_ids=[]
    start = datetime.strptime(str(start_date), "%Y%m%d")
    stop = datetime.strptime(str(stop_date), "%Y%m%d")    
    while start < stop:
        start = start + timedelta(days=1)  # increase day one by one
        date =  int(start.strftime("%Y%m%d"))
        try:
            all_ids.append(get_IDs(smite, date, game_mode, hour=-1))
        except NoResultError:
            print("No result for", date)
    return(all_ids)

In [5]:
def get_match_info(smite, match_ids, raw_folder, sorted_folder):
    """ Given list of matches, writes (raw and sorted) csv files of 100 matches each,
        labeled by earliest and latest game in YYYYMMDDHHmm-YYYYMMDDHHmm format.
        sorted files are sorted by minematch().
        Example filename: SMITE_raw_match_201610042230-201610042315
        Params:
        smite: smite-python SmiteClient object
        match_ids: list of valid match_ids
        raw_folder: folder (in current directory) to place raw csv files
        sorted_folder: folder (in current directory) to place sorted csv files     
    """
    print("Begun")
    df_raw = pd.DataFrame()
    df_sorted = pd.DataFrame()
    num_matches = 0
    tot_num_matches = len(match_ids)
    
    for id in match_ids:
        num_matches += 1       
#        if num_matches%50==0:
#            print(num_matches, "of", tot_num_matches)       
        try:
            match = pd.DataFrame(smite.get_match_details(id))
        except NoResultError:
            print(id, "returned no data")
            continue
        mined = minematch(match)
        df_raw = df_raw.append(match)
        df_sorted = df_sorted.append(mined)   
        
        # save every 100 matches (raw and sorted)
        if num_matches%100==0 or num_matches==tot_num_matches:
            # get min/max date for naming file
            min_date = pd.to_datetime(df_raw.Entry_Datetime).min().strftime('%Y%m%d%H%M')
            max_date = pd.to_datetime(df_raw.Entry_Datetime).max().strftime('%Y%m%d%H%M')         
            # write files (and reset match dfs)
            os.chdir(raw_folder)
            df_raw.to_csv('SMITE_raw_match_{}-{}.csv'.format(min_date,max_date), index = False)
            os.chdir('..')
            df_raw = pd.DataFrame()
            os.chdir(sorted_folder)
            df_sorted.to_csv('SMITE_sorted_match_{}-{}.csv'.format(min_date,max_date), index = False)
            os.chdir('..')
            df_sorted = pd.DataFrame()
            print('SMITE file written.', num_matches, "written so far." )
        if num_matches%250==0:
            print("SMITE API usage update:")
            print(smite.get_data_used())
    print("All match info retrieved.")
    
def minematch(match):
    '''given a dataframe containing all match info, returns a df of relevant information'''
    # return None if any god slots are missing, or someone never bought their first relic (afk)
    if any(match.GodId==0):
        return(None)
    if any(match.ActiveId1.isnull()) or any(match.ActiveId1==0):
        return(None)
    
    # choose subset of variables to keep 
    df = match.loc[:,['Entry_Datetime',
                      'Match',
                      'name',
                      'Win_Status',
                      'GodId',
#                      'Reference_Name',
#                      'Item_Active_1',
#                      'Item_Active_2',
#                      'Item_Purch_1',
#                      'Item_Purch_2',
#                      'Item_Purch_3',
#                      'Item_Purch_4',
#                      'Item_Purch_5',
#                      'Item_Purch_6',
                      'ActiveId1',
                      'ActiveId2',
                      'ItemId1', 
                      'ItemId2',
                      'ItemId3',
                      'ItemId4',
                      'ItemId5',
                      'ItemId6',
                      'Gold_Per_Minute',
#                      'Time_In_Match_Seconds',
                      'Minutes'                     
#                      'Kills_First_Blood',
#                      'Kills_Fire_Giant',
#                      'Kills_Gold_Fury',
#                      'Kills_Phoenix',
#                      'Mastery_Level',
#                      'Conquest_Tier',
#                      'Conquest_Wins'
                     ]]
    # add Win_Ratio
#    df["Conquest_Win_Ratio"]=round(match.Conquest_Wins/(match.Conquest_Wins + match.Conquest_Losses),2) 
    
    # change some variable names
    df = df.rename(columns={"ActiveId1" : "relic0",
                            "ActiveId2" : 'relic1',
                            'Entry_Datetime' : 'match_time',
                            'name' : "game_mode_name",
                            'Match' : "match_id",
                            'Win_Status' : "win",
                            'GodId' : 'god_id',
                            'Reference_Name' : "god_name",
                            'ItemId1' : 'item0', 
                            'ItemId2' : 'item1',
                            'ItemId3' : 'item2',
                            'ItemId4' : 'item3',
                            'ItemId5' : 'item4',
                            'ItemId6' : 'item5',
#                            'Time_In_Match_Seconds' : "duration"
                            'Minutes' : "duration_min"                            
                           }) 
    df.win=df.win.replace({'Winner': True, 'Loser': False})    
    return(df)

Using smite-python by jaydenkieran as wrapper for SMITE API requests, with smite.py in working directory.

https://github.com/jaydenkieran/smite-python/blob/master/smite.py

Every call to the API is counting as 2 requests, either due to the wrapper or the SMITE API. API method information: http://smite-python.readthedocs.io/en/latest/api.html

SMITE measures time in Universal Time Coordinated (UTC), 8 hours ahead of Pacific time. But Smite API appears to reset request counts at 11:00PM pacific. SMITE API only allows 7500 request a day.

Patch notes happen every 2 weeks on a wednesday. Not sure when they actually go live. Patch 3.21 happened on 11/02/2016, but as of 11/06/2016 ping() still returns patch 3.20 (3.21 on 11/9)


In [18]:
def main():   
    # edit to choose what main's function should be
    get_matches = False  # get all match info for a particular day
    get_matchIDs = False  # get all valid matchids between two dates (could be useful for scraping)
    update_gods = False  # update if there are new gods/changes 
    update_items = False # if there are new items/changes  

    # for get_matches
    date = 20161101
    hour = -1
    raw_folder    = 'SMITE_raw'
    sorted_folder = 'SMITE_sorted'
    
    # for get_matchIDs
    start_date = 20161107
    end_date = 20161114
    
    # for both methods  
    game_mode = 451  
    #    Gamemodes:
    # 451 -ConquestLeague (ranked)
    # 426 -Conquest       (casual)
    # 440 -Ranked Duel (1v1 joust map)
    # 450 -Joust Ranked (3v3)
    # 448 -Joust Casual
    # date format: 20141231  
    # -1 or 24 (all hours)
    # 0-23  (1 hour UTC)
    
####### Initialize Smite API connection  #######  
    # import config
    config = readfile('config')
    key = config['smite']['smitekey{}'.format(1)] # Micah's key
    devID = config['smite']['smitedevID{}'.format(1)] # Micah's devID
    smite = SmiteClient(devID,key)
    print(smite.ping())  
    
############### main method ########################
    # update item and god files in wd
    if update_gods:
        get_all_gods(smite)
    if update_items:
        get_all_items(smite)
    
    if get_matches:
        match_ids = get_IDs(smite, date, game_mode, hour)
        get_match_info(smite, match_ids, raw_folder, sorted_folder)
        
    if get_matchIDs:
        all_match_ids = get_all_match_IDs(smite, start_date, end_date, game_mode)
        if game_mode == 451:
            mode = 'ranked'
        elif game_mode == 426:
            mode = 'casual'
        elif game_mode == 450:
            mode = 'joust_ranked'
        elif game_mode == 440:
            mode = 'duel_ranked'
        else:
            mode = 'othermodes'               
        pickle.dump(all_match_ids, open("SMITE_data/{}_match_ids_{}-{}.p".format(mode, start_date, end_date), "wb"))
            
if __name__ == '__main__':
    main()


SmiteAPI (ver 3.21.0.32636) [PATCH - 3.21] - Ping successful. Server Date:11/19/2016 6:04:14 AM

In [6]:
"""
# Configure for interactions with Smite API outside of main method
config = readfile('config')
key = config['smite']['smitekey{}'.format(1)] # Micah's key
devID = config['smite']['smitedevID{}'.format(1)] # Micah's devID
smite = SmiteClient(devID,key)
print(smite.ping())
"""


SmiteAPI (ver 3.21.0.32636) [PATCH - 3.22] - Ping successful. Server Date:11/21/2016 6:14:40 PM

In [1]:
"""
#failed_matches_list = pickle.load(open("SMITE_data/failed_match_list.p", "rb"))
len(failed_matches_list)
raw_folder    = 'SMITE_scraped_raw_joust'
sorted_folder = 'SMITE_scraped_parsed_joust'
get_match_info(smite, failed_matches_list, raw_folder, sorted_folder)
"""


Out[1]:
'\n#failed_matches_list = pickle.load(open("SMITE_data/failed_match_list.p", "rb"))\nlen(failed_matches_list)\nraw_folder    = \'SMITE_scraped_raw_joust\'\nsorted_folder = \'SMITE_scraped_parsed_joust\'\nget_match_info(smite, failed_matches_list, raw_folder, sorted_folder)\n'