# AUTOGENERATED! DO NOT EDIT! File to edit: 20_data.ipynb (unless otherwise specified).

__all__ = ['read_csv', 'concat', 'add_tables', 'prepare_labrie_data', 'prepare_braverman_data',
           'prepare_philander_data', 'generate_bets', 'check_data', 'summarise_app', 'summarise_providers',
           'plot_player_career', 'plot_player_career_split', 'plot_provider_dates', 'plot_provider_bets']

# Cell
import pandas as pd
def read_csv(file, parse_dates=[], index_col=None, delimiter=",", dummy_data=False):
    "Read csv files into a pandas dataframe."
    df = pd.read_csv(
        file, parse_dates=parse_dates, index_col=index_col, delimiter=delimiter
    )

    return df

# Cell
def concat(dfs, axis=0):
    "This method is a wrapper of pandas' **concat** function. See [here](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.concat.html) for details."

    df = pd.concat(dfs, axis=axis)
    return df

# Cell
def add_tables(t1, t2, same_columns=False):
    "Joins two tables (the second to the right hand side of the first), adding '_2' to column names if same_columns parameter is True."

    if same_columns:
        t2.columns = [name + "_2" for name in t2.columns]
    combined = pd.concat([t1, t2.reindex(t1.index)], axis=1)
    return combined

# Cell
def prepare_labrie_data(filename, savedir="labrie_individuals/", loud=False, year=2008):
    "Splits the original labrie data into CSV files for each individual's transactions and renames the columns to be compatable with the rest of the gamba library."

    labrie_data = None

    if year == 2008:
        labrie_data = pd.read_csv(filename, delimiter="\t", parse_dates=["Date"])
    elif year == 2007:
        labrie_data = pd.read_csv(filename, parse_dates=["Date"])

    # rename columns to make them compatable with gamba.measures
    if loud:
        print("original columns:", list(labrie_data.columns))

    if year == 2008:
        labrie_data.columns = [
            "player_id",
            "bet_time",
            "bet_size",
            "payout_size",
            "bet_count",
        ]
        labrie_data.to_csv("gamba_ready_labrie_data_2008.csv", index=False)
    elif year == 2007:
        labrie_data.columns = [
            "player_id",
            "bet_time",
            "product_id",
            "bet_size",
            "payout_size",
            "bet_count",
        ]
        labrie_data.to_csv("gamba_ready_labrie_data_2007.csv", index=False)

    if loud:
        print("better columns:", list(labrie_data.columns))

    # split_individual_transactions(labrie_data, savedir)

    if loud:
        print("LaBrie data ready to use!")

    return labrie_data

# Cell
def prepare_braverman_data(filename, loud=False):
    "Splits the original Braverman and Shaffer data into CSV files for each indivdiual's transactions, and renames the columns to be compatable with the rest of the gamba library."

    braverman_data = pd.read_csv(filename, parse_dates=["TimeDATE"], delimiter="\t")

    braverman_data.columns = [
        "player_id",
        "bet_time",
        "bet_size",
        "payout_size",
        "bet_count",
    ]

    # split_individual_transactions(raw_data, 'braverman_individuals/')

    if loud:
        print("Braverman data ready to use!")

    braverman_data.to_csv("gamba_ready_braverman_data.csv", index=False)
    return braverman_data

# Cell
import numpy as np
def prepare_philander_data(filename, loud=False):
    "Loads in the analytic data set of high-risk internet gamblers and removes the UserID, Sereason, random, and clustering columns as described in Philander's 2014 study."

    analytic_data = read_csv(filename, delimiter='\t')
    philander_data = analytic_data.copy()
    philander_data['self_exclude'] = np.where(philander_data['Sereason'] == 3, 1, 0) # apply the binary self-exclude technique (middle of page 5)
    philander_data.drop(labels=['Sereason','random','p2clusteringactivity','p2clusterhalf1','p2clusterhalf2'], axis=1, inplace=True)
    philander_data.columns = ['player_id', 'country', 'gender','age','total_wagered','num_bets','frequency','duration','bets_per_day','net_loss',
                              'intensity','variability','frequency_1m','trajectory',
                              'z_intensity','z_variability','z_frequency','z_trajectory','self_exclude']
    if loud:
        print(len(philander_data), 'players loaded')

    return philander_data

# Cell
import gamba as gb, pandas as pd, random
import datetime

def generate_bets(n=200):
    df = pd.DataFrame()

    df['player_id'] = [1] * n
    df['bet_size'] = [random.randint(0,20) for _ in range(n)]
    df['bet_time'] = [datetime.datetime.now() + random.random() * datetime.timedelta(days=500) for _ in range(n)]
    df['payout_size'] = [bet * 2 if (random.random() < 0.5) else 0 for bet in df['bet_size'] ]

    df['payout_time'] = [bet_time + random.random() * datetime.timedelta(minutes=1) for bet_time in df['bet_time']]
    df['decimal_odds'] = [2.0] * n

    return df

# Cell
def check_data(dataframe):
    "Make sure that your data is in the gamba standard format (has the right column names). This method will raise an exception if the format is incorrect, and will do nothing if it is correct."

    acceptable_names = ['player_id','bet_size','bet_time','payout_size','payout_time','decimal_odds','house_edge','game_type','provider']

    for name in dataframe.columns:
        if name not in acceptable_names:
            raise Exception('invalid column name provided, expecting one of', acceptable_names)

# Cell
def summarise_app(player_bets, dapp=False):
    "Prints out some basic information about a gambling or gambling-like application given a collection of bets made through that application. Data displayed includes the number of users, the number of game types provided, the number of bets placed, the total value of the bets and the payouts, the time of the first bet, and the time of the last."

    users = set(player_bets["player_id"].values)
    games = set(player_bets["game_type"].values)
    bets = player_bets["bet_size"].sum()
    payouts = player_bets["payout_size"].sum()

    # this part is specific to gambling DApps (see Scholten 2020)
    if dapp:
        start_block = player_bets["block_number"].min()
        end_block = player_bets["block_number"].max()

    start = player_bets["bet_time"].min()
    end = player_bets["bet_time"].max()

    print("users:", len(users))
    print("games:", len(games))
    print("num bets:", len(player_bets))
    print("bet value:", bets)
    print("payout value:", payouts)

    if dapp:
        print("start:", start, int(start_block))
        print("end:", end, int(end_block))
    else:
        print("start:", start)
        print("end:", end)
    print("")

# Cell
def summarise_providers(player_bets, providers, game_types=['coinflip','onedice','twodice','roll']):
    "Create a table containing summary data for providers using a collection of player bets. Summary includes the number of unique users and games, the total value of bets and payouts, the starting and ending block numbers, and the time the starting and ending blocks occurred."

    all_summaries = pd.DataFrame()
    for provider in providers:
        provider_bets = player_bets[(player_bets['provider'] == provider) & (player_bets['game_type'].isin(game_types))]

        users = len(set(provider_bets["player_id"].values))
        games = len(set(provider_bets["game_type"].values))
        bets = provider_bets["bet_size"].sum()
        payouts = provider_bets["payout_size"].sum()
        start_block = provider_bets["block_number"].min()
        end_block = provider_bets["block_number"].max()
        start = provider_bets["bet_time"].min()
        end = provider_bets["bet_time"].max()

        summary = pd.DataFrame()
        summary['values'] = ['Unique Users', 'Games','Bet Value','Payout Value','Start Block','End Block','Start Time','End Time']
        summary[provider] = [users, games, bets, payouts, int(start_block), int(end_block), start, end]


        all_summaries['values'] = summary['values']
        all_summaries[provider] = summary[provider]

    all_summaries.set_index('values', inplace=True)
    return all_summaries

# Cell
import matplotlib.pyplot as plt
def plot_player_career(player_df, savename=None):
    "Creates a candlestick-style plot of a players betting activity over the course of their career. This works best on regularly-spaced sequential data but can also provide insight into intra-session win/loss patterns."

    plt.figure(figsize=[5, 3])
    previous_y_end = 0
    for i, bet in player_df.iterrows():
        bet_size = bet["bet_size"]
        payout_size = bet["payout_size"]
        bet_time = bet["bet_time"]
        payout_time = bet["payout_time"]

        start_y = previous_y_end
        end_y = 0

        # if bet loses
        if payout_size < bet_size:
            end_y = start_y - bet_size
            # plt.plot([2*i, 2*i + 1], [bet_size, payout_size], marker='o', color='red')
            plt.plot(
                [i, i], [start_y, end_y], marker="o", color="#d30505", markersize=12
            )
        else:
            end_y = start_y + payout_size
            # plt.plot([2*i, 2*i + 1], [bet_size, payout_size], marker='o', color='green')
            plt.plot(
                [i, i], [start_y, end_y], marker="o", color="#00B007", markersize=12
            )

        previous_y_end = end_y

    plt.xlabel(None)
    if savename != None:
        plt.savefig(savename, dpi=200, transparent=True)

    return plt

# Cell
def plot_player_career_split(player_df):
    "Plot a player's betting and payout trajectory on a single plot, with green indicating payouts (top) and red indicating bets (bottom). A cumulative value line is also plotted between the two. Note that the player_df must include both bet_size and payout_size columns."

    plt.figure()

    previous_y_end = 0
    for i, bet in player_df.iterrows():
        bet_size = bet["bet_size"]
        payout_size = bet["payout_size"]
        bet_time = bet["bet_time"]
        payout_time = bet["payout_time"]

        start_y = previous_y_end
        end_y = 0

        # if bet loses
        if payout_size < bet_size:
            end_y = start_y - bet_size
            # plt.plot([2*i, 2*i + 1], [bet_size, payout_size], marker='o', color='red')
            plt.plot([i, i], [start_y, end_y], marker="o", color="red")
        else:
            end_y = start_y + payout_size
            # plt.plot([2*i, 2*i + 1], [bet_size, payout_size], marker='o', color='green')
            plt.plot([i, i], [start_y, end_y], marker="o", color="green")

        previous_y_end = end_y

    bets = player_df["bet_size"].values
    payouts = player_df["payout_size"].values
    plt.plot(
        range(len(bets)),
        np.cumsum(-bets),
        marker="o",
        color="red",
        label="Cumulative Bets",
    )
    plt.plot(
        range(len(payouts)),
        np.cumsum(payouts),
        marker="o",
        color="green",
        label="Cumulative Payouts",
    )
    plt.legend()
    plt.xlim(0, len(bets) * 1.02)
    plt.ylim(-max([sum(bets), sum(payouts)]), max([sum(bets), sum(payouts)]))
    return plt

# Cell
def plot_provider_dates(player_bets, providers, provider_labels=None):
    """
    Visualises the start and end dates of bets from one or more providers on a stacked gantt style plot.

    """
    fig = plt.figure(figsize=[8,1.5])

    for i, provider in enumerate(providers):
        provider_bets = player_bets[(player_bets['provider'] == provider)]
        start = provider_bets["bet_time"].min()
        end = provider_bets["bet_time"].max()

        plt.plot([start, end], [i,i], label=provider)
        plt.scatter([start, end], [i,i], s=100, marker='|')

    ax = fig.axes[0]
    ax.xaxis.set_major_locator(mdates.MonthLocator([1,4,7,10])) # ticks on first day of each quarter
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y')) # format of only month (3 letter abbr)
    if provider_labels == None:
        plt.yticks([0,1,2], providers)
    else:
        plt.yticks(range(len(providers)), provider_labels)
    plt.ylim(-0.5, len(providers)-0.5)
    plt.grid(True)
    return plt

# Cell
import matplotlib.pyplot as plt, matplotlib.dates as mdates
from matplotlib.ticker import FuncFormatter
#export
def plot_provider_bets(player_bets, providers, provider_labels=None):
    "Visualises the cumulative number of bets from one or more providers."

    fig = plt.figure(figsize=[8,3])

    def millions(x, pos):
        'The two args are the value and tick position'
        return '%1.1fM' % (x*1e-6)

    formatter = FuncFormatter(millions)

    for i, provider in enumerate(providers):
        provider_bets = player_bets[(player_bets['provider'] == provider)].sort_values('bet_time')
        plt.plot(provider_bets['bet_time'], provider_bets['bet_size'].cumsum(), label=provider_labels[i])

    player_bets.sort_values('bet_time', inplace=True)
    plt.plot(player_bets['bet_time'], player_bets['bet_size'].cumsum(), label='All Applications')
    ax = fig.axes[0]
    ax.xaxis.set_major_locator(mdates.MonthLocator([1,4,7,10])) # ticks on first day of each quarter
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %Y')) # format of only month (3 letter abbr)

    ax.yaxis.set_major_formatter(formatter)
    plt.grid(True)
    plt.ylabel('Total Value of Bets, in ETH')
    plt.legend()
    plt.savefig('provider_bets.pdf', bbox_inches='tight')
    return plt