def generate_elo(df,counts_i):
    players_list = np.union1d(df.w_name, df.l_name)
    players_elo = dict(zip(list(players_list), [elo.Rating() for __ in range(len(players_list))]))
    surface_elo = {}
    for surface in ('Hard','Clay','Grass'):
        surface_elo[surface] = dict(zip(list(players_list), [elo.Rating() for __ in range(len(players_list))])) 

    elo_1s, elo_2s = [],[]
    surface_elo_1s, surface_elo_2s = [],[]
    elo_obj = elo.Elo_Rater()

    # update player elo from every recorded match
    for i, row in df.iterrows():
        surface = row['surface']; is_gs = row['is_gs']
        # append elos, rate, update
        w_elo,l_elo = players_elo[row['w_name']],players_elo[row['l_name']]
        elo_1s.append(w_elo.value);elo_2s.append(l_elo.value)    
        elo_obj.rate_1vs1(w_elo,l_elo,is_gs,counts=counts_i)


        surface_elo_1s.append(surface_elo[surface][row['w_name']].value if surface in ('Hard','Clay','Grass') else w_elo.value)
        surface_elo_2s.append(surface_elo[surface][row['l_name']].value if surface in ('Hard','Clay','Grass') else l_elo.value)
        if surface in ('Hard','Clay','Grass'):
            new_elo1, new_elo2 = elo_obj.rate_1vs1(surface_elo[surface][row['w_name']],surface_elo[surface][row['l_name']],is_gs,counts=counts_i)

    # add columns
    if counts_i:
        df['w_elo_538'], df['l_elo_538'] = elo_1s, elo_2s
        df['w_sf_elo_538'], df['l_sf_elo_538'] = surface_elo_1s, surface_elo_2s
    else:
        df['w_elo'], df['l_elo'] = elo_1s, elo_2s
        df['w_sf_elo'], df['l_sf_elo'] = surface_elo_1s, surface_elo_2s
    return df
def generate_elo_columns(arr, counts_538):
    # print('arr[0]: ', arr[0])
    # print('arr[1]: ', arr[1])
    # print('arr[0].dtype', arr[:, 0].dtype)
    # print('arr[1].dtype', arr[:, 1].dtype)
    # print('arr[:, :2]', arr[:, :2])
    # for s in arr:
    #     if isinstance(s[1], bool):
    #         print('s: ', s)
    # print('is: ', [s for s in arr if isinstance(s[0], bool))
    # players_set = np.unique(arr[:, :2].astype(str))
    player_names = arr[:, :2].flatten()
    players_set = np.where(player_names!=player_names, '', player_names).tolist()
    # players_set = list(set(list(np.concatenate(arr[:, 0], arr[:, 1]))))
    # player_count = len(players_set)
    # print('player_count: ', player_count)
    # initial_ratings = [elo.Rating() for _ in range(player_count)]
    # zipped = zip(
    #     players_set,
    #     [elo.Rating() for _ in range(player_count)]
    # )
    # # print('zipped: ', zipped)
    # players_elo = dict(zip(
    #     players_set,
    #     [elo.Rating() for _ in range(player_count)]
    # )) # can use default dict here?
    players_elo = {}
    for player in players_set:
        # print('player: ', player)
        players_elo[player] = elo.Rating()

    match_elos = np.zeros([arr.shape[0], 2])
    elo_obj = elo.Elo_Rater()

    # update player elo from every recorded match
    for i in range(arr.shape[0]):
        w_name, l_name = arr[i][:2]

        if w_name != w_name or l_name != l_name:
            match_elos[i] = np.nan, np.nan
            continue

        match_elos[i] = players_elo[w_name].value, players_elo[l_name].value
        elo_obj.rate_1vs1(players_elo[w_name], players_elo[l_name], arr[i][2], counts_538)

    return match_elos[:,0], match_elos[:,1]
def generateEloColumnsWithHistory(arr, counts_538):
    playerEloHistory = defaultdict(list)
    players_set = np.unique(arr[:, :2])
    players_elo = dict(zip(
        players_set,
        [elo.Rating() for __ in range(len(players_set))]
    )) # can use default dict here?

    match_elos = np.zeros([arr.shape[0], 2])
    elo_obj = elo.Elo_Rater()

    # update player elo from every recorded match
    for i in range(arr.shape[0]):
        w_name, l_name = arr[i][:2]
        isGrandSlam = arr[i][2]
        date = datetime.datetime.strptime(arr[i][3], '%Y-%m-%d')

        match_elos[i] = players_elo[w_name].value, players_elo[l_name].value
        elo_obj.rate_1vs1(players_elo[w_name], players_elo[l_name], 0, counts_538)

        playerEloHistory[w_name].append({ 'date': date, 'newElo': players_elo[w_name].value, 'won': 1 })
        playerEloHistory[l_name].append({ 'date': date, 'newElo': players_elo[l_name].value, 'won': 0 })

    return match_elos[:,0], match_elos[:,1], playerEloHistory, players_elo
def generate_elo_stephanie(df, counts, h1, h2):
    players_list = np.union1d(df.w_name, df.l_name)
    players_elo = dict(
        zip(list(players_list),
            [elo.Rating() for __ in range(len(players_list))]))
    surface_elo = {}
    for surface in ('Hard', 'Clay', 'Grass'):
        surface_elo[surface] = dict(
            zip(list(players_list),
                [elo.Rating() for __ in range(len(players_list))]))

    elo_1s, elo_2s = [], []
    surface_elo_1s, surface_elo_2s = [], []
    elo_obj = elo.Elo_Rater()

    k1, k2 = 5.3, 16

    # update player elo from every recorded match
    for i, row in df.iterrows():
        surface = row['surface']
        is_gs = row['is_gs']
        tny_name = row['tny_name']
        tny_round_name = row['tourney_round_name']
        #delta1 = row['newwdelta1'] ; delta2 = row['newwdelta2']
        delta1 = row['minusnewwdelta1']
        delta2 = row['minusnewwdelta2']
        # append elos, rate, update
        w_elo, l_elo = players_elo[row['w_name']], players_elo[row['l_name']]

        elo_1s.append(w_elo.value)
        elo_2s.append(l_elo.value)

        # get different kinds of precalculated scalers
        # s_tournament_w = row['s_tournament_w']
        # s_tournament_l = row['s_tournament_l']
        # s_match_duration_w = row['s_match_duration_w']
        # s_match_duration_l = row['s_match_duration_l']
        # tny_name = row['tny_name']
        # tny_round_name = row['tourney_round_name']
        # is_gs = row['is_gs']
        # surface = row['surface']
        # w_name = row['w_name']
        # l_name = row['l_name']

        elo_obj.rate_1vs1_stephanie(w_elo,
                                    l_elo,
                                    k1,
                                    k2,
                                    delta1,
                                    delta2,
                                    is_gs,
                                    counts,
                                    tny_name,
                                    tny_round_name,
                                    h1=h1,
                                    h2=h2)

        surface_elo_1s.append(surface_elo[surface][row['w_name']].
                              value if surface in ('Hard', 'Clay',
                                                   'Grass') else w_elo.value)
        surface_elo_2s.append(surface_elo[surface][row['l_name']].
                              value if surface in ('Hard', 'Clay',
                                                   'Grass') else l_elo.value)
        if surface in ('Hard', 'Clay', 'Grass'):
            elo_obj.rate_1vs1_stephanie(w_elo,
                                        l_elo,
                                        k1,
                                        k2,
                                        delta1,
                                        delta2,
                                        is_gs,
                                        counts,
                                        tny_name,
                                        tny_round_name,
                                        h1=h1,
                                        h2=h2)

    # add columns
    if counts:
        df['w_elo_538'], df['l_elo_538'] = elo_1s, elo_2s
        df['w_sf_elo_538'], df['l_sf_elo_538'] = surface_elo_1s, surface_elo_2s
    else:
        df['w_elo'], df['l_elo'] = elo_1s, elo_2s
        df['w_sf_elo'], df['l_sf_elo'] = surface_elo_1s, surface_elo_2s
    return df
def generate_elo(df, counts_i):
    players_list = np.union1d(df.w_name, df.l_name)
    players_elo = dict(
        zip(list(players_list),
            [elo.Rating() for __ in range(len(players_list))]))
    surface_elo = {}
    for surface in ('Hard', 'Clay', 'Grass'):
        surface_elo[surface] = dict(
            zip(list(players_list),
                [elo.Rating() for __ in range(len(players_list))]))

    elo_1s, elo_2s = [], []
    surface_elo_1s, surface_elo_2s = [], []
    elo_obj = elo.Elo_Rater()

    # update player elo from every recorded match
    for i, row in df.iterrows():
        # if surface in ('Hard','Clay','Grass'):
        #     print "same object: ", players_elo[row['w_name']] is surface_elo[surface][row['w_name']]
        surface = row['surface']
        is_gs = row['is_gs']
        # append elos, rate, update
        w_elo, l_elo = players_elo[row['w_name']], players_elo[row['l_name']]
        elo_1s.append(w_elo.value)
        elo_2s.append(l_elo.value)

        tny_name = row['tny_name']
        tny_round_name = row['tourney_round_name']

        # get different kinds of precalculated scalers
        # s_tournament_w = row['s_tournament_w']
        # s_tournament_l = row['s_tournament_l']
        # s_match_duration_w = row['s_match_duration_w']
        # s_match_duration_l = row['s_match_duration_l']
        # w_name = row['w_name']
        # l_name = row['l_name']

        # original
        elo_obj.rate_1vs1(w_elo, l_elo, is_gs, counts=counts_i)

        # elo_obj.rate_1vs1(w_elo,l_elo,is_gs, counts=counts_i, tny_name=tny_name, tny_round_name=tny_round_name)

        surface_elo_1s.append(surface_elo[surface][row['w_name']].
                              value if surface in ('Hard', 'Clay',
                                                   'Grass') else w_elo.value)
        surface_elo_2s.append(surface_elo[surface][row['l_name']].
                              value if surface in ('Hard', 'Clay',
                                                   'Grass') else l_elo.value)
        if surface in ('Hard', 'Clay', 'Grass'):
            elo_obj.rate_1vs1(surface_elo[surface][row['w_name']],
                              surface_elo[surface][row['l_name']],
                              is_gs,
                              counts=counts_i)
            # elo_obj.rate_1vs1(surface_elo[surface][row['w_name']],surface_elo[surface][row['l_name']], counts=counts_i, tny_name=tny_name, tny_round_name=tny_round_name)

    # add columns
    if counts_i:
        df['w_elo_538'], df['l_elo_538'] = elo_1s, elo_2s
        df['w_sf_elo_538'], df['l_sf_elo_538'] = surface_elo_1s, surface_elo_2s
    else:
        df['w_elo'], df['l_elo'] = elo_1s, elo_2s
        df['w_sf_elo'], df['l_sf_elo'] = surface_elo_1s, surface_elo_2s

    return df