import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler, LabelEncoder
import datetime
import warnings
from string import punctuation
import re
import math
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from keras.callbacks import Callback, EarlyStopping
from keras.models import Model
from keras.layers import Input, Dense, Concatenate, Reshape, Dropout, merge, Add
from keras.layers.embeddings import Embedding
from sklearn.model_selection import KFold,GroupKFold

warnings.filterwarnings('ignore')
pd.set_option('expand_frame_repr', False)
pd.set_option('display.max_rows', 50)
pd.set_option('display.max_columns', 200)

# evaluation metric
def crps(y_true, y_pred):
    y_true = np.clip(np.cumsum(y_true, axis=1), 0, 1)
    y_pred = np.clip(np.cumsum(y_pred, axis=1), 0, 1)
    return ((y_true - y_pred) ** 2).sum(axis=1).sum(axis=0) / (199 * y_true.shape[0])

# 提交的作品将根据连续排列的概率分数(CRPS)进行评估。
# 对于每个PlayId，您必须预测获得或丢失码数的累积概率分布。换句话说，您预测的每一列表示该队在比赛中获得<=那么多码的概率。
def return_step(x):
    temp = np.zeros(199)
    temp[x + 99:] = 1
    return temp

def strtoseconds(txt):
    txt = txt.split(':')
    ans = int(txt[0]) * 60 + int(txt[1]) + int(txt[2]) / 60
    return ans

def strtofloat(x):
    try:
        return float(x)
    except:
        return -1

def map_weather(txt):
    ans = 1
    if pd.isna(txt):
        return 0
    if 'partly' in txt:
        ans *= 0.5
    if 'climate controlled' in txt or 'indoor' in txt:
        return ans * 3
    if 'sunny' in txt or 'sun' in txt:
        return ans * 2
    if 'clear' in txt:
        return ans
    if 'cloudy' in txt:
        return -ans
    if 'rain' in txt or 'rainy' in txt:
        return -2 * ans
    if 'snow' in txt:
        return -3 * ans
    return 0

def OffensePersonnelSplit(x):
    dic = {'DB': 0, 'DL': 0, 'LB': 0, 'OL': 0, 'QB': 0, 'RB': 0, 'TE': 0, 'WR': 0}
    for xx in x.split(","):
        xxs = xx.split(" ")
        dic[xxs[-1]] = int(xxs[-2])
    return dic

def DefensePersonnelSplit(x):
    dic = {'DB': 0, 'DL': 0, 'LB': 0, 'other': 0}
    for xx in x.split(","):
        xxs = xx.split(" ")
        if dic.__contains__(xxs[-1]):
            dic[xxs[-1]] = int(xxs[-2])
        else:
            dic['other'] += int(xxs[-2])
    return dic

def orientation_to_cat(x):
    x = np.clip(x, 0, 360 - 1)
    try:
        return str(int(x / 15))
    except:
        return "nan"

def transform_time_all(str1, quarter):
    if quarter <= 4:
        return 15 * 60 - (int(str1[:2]) * 60 + int(str1[3:5])) + (quarter - 1) * 15 * 60
    if quarter == 5:
        return 10 * 60 - (int(str1[:2]) * 60 + int(str1[3:5])) + (quarter - 1) * 15 * 60

def clean_StadiumType(txt):
    if pd.isna(txt):
        return np.nan
    txt = txt.lower()
    txt = ''.join([c for c in txt if c not in punctuation])
    txt = re.sub(' +', ' ', txt)
    txt = txt.strip()
    txt = txt.replace('outside', 'outdoor')
    txt = txt.replace('outdor', 'outdoor')
    txt = txt.replace('outddors', 'outdoor')
    txt = txt.replace('outdoors', 'outdoor')
    txt = txt.replace('oudoor', 'outdoor')
    txt = txt.replace('indoors', 'indoor')
    txt = txt.replace('ourdoor', 'outdoor')
    txt = txt.replace('retractable', 'rtr.')
    return txt

def transform_StadiumType(txt):
    if pd.isna(txt):
        return np.nan
    if 'outdoor' in txt or 'open' in txt:
        return 1
    if 'indoor' in txt or 'closed' in txt:
        return 0

    return np.nan

def get_score(y_pred, cdf, w, dist_to_end):
    y_pred = int(y_pred)
    if y_pred == w:
        y_pred_array = cdf.copy()
    elif y_pred - w > 0:
        y_pred_array = np.zeros(199)
        y_pred_array[(y_pred - w):] = cdf[:(-(y_pred - w))].copy()
    elif w - y_pred > 0:
        y_pred_array = np.ones(199)
        y_pred_array[:(y_pred - w)] = cdf[(w - y_pred):].copy()
    y_pred_array[-1] = 1
    y_pred_array[(dist_to_end + 99):] = 1
    return y_pred_array

def euclidean_distance(x1, y1, x2, y2):
    x_diff = (x1 - x2) ** 2
    y_diff = (y1 - y2) ** 2

    return np.sqrt(x_diff + y_diff)

def min_tackle_time(dist, v, a):
    return (np.sqrt(v * v + 2 * a * dist) - v) / a

def drop(train):
    # drop_cols += ["Orientation", "Dir"]

    play_drop = ['PlayId', "TimeHandoff", "TimeSnap", "GameClock", "DefensePersonnel", "OffensePersonnel",
                 'FieldPosition', 'PossessionTeam', 'HomeTeamAbbr', 'VisitorTeamAbbr',
                 'HomeScoreBeforePlay', 'VisitorScoreBeforePlay', 'TeamOnOffense', 'Stadium']
    player_drop = ['DisplayName', 'PlayerBirthDate', "IsRusher", "NflId", "NflIdRusher", "Dir",
                   'Dir_rad', 'Ori_rad', "PlayDirection", 'Orientation', 'Rusher_X', 'Rusher_Y',
                   'dist_to_rusher', 'time_to_rusher']
    environment_drop = ["WindSpeed", "WindDirection", "Season", "GameWeather", 'Location', 'GameWeather_process',
                        'Turf']
    drop_cols = player_drop + play_drop + environment_drop
    train.drop(drop_cols, axis=1, inplace=True)
    return train

def preprocess(train):
    # fix some encode https://www.kaggle.com/bgmello/neural-networks-feature-engineering-for-the-win
    train.loc[train.VisitorTeamAbbr == "ARI", 'VisitorTeamAbbr'] = "ARZ"
    train.loc[train.HomeTeamAbbr == "ARI", 'HomeTeamAbbr'] = "ARZ"

    train.loc[train.VisitorTeamAbbr == "BAL", 'VisitorTeamAbbr'] = "BLT"
    train.loc[train.HomeTeamAbbr == "BAL", 'HomeTeamAbbr'] = "BLT"

    train.loc[train.VisitorTeamAbbr == "CLE", 'VisitorTeamAbbr'] = "CLV"
    train.loc[train.HomeTeamAbbr == "CLE", 'HomeTeamAbbr'] = "CLV"

    train.loc[train.VisitorTeamAbbr == "HOU", 'VisitorTeamAbbr'] = "HST"
    train.loc[train.HomeTeamAbbr == "HOU", 'HomeTeamAbbr'] = "HST"

    # ——————— play ———————
    ## GameClock
    train['GameClock_sec'] = train['GameClock'].apply(strtoseconds)
    # train["GameClock_minute"] = train["GameClock"].apply(lambda x: x.split(":")[0])  # hour
    train['time_end'] = train.apply(lambda x: transform_time_all(x.loc['GameClock'], x.loc['Quarter']), axis=1)

    ## Time
    train['TimeHandoff'] = train['TimeHandoff'].apply(lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ"))
    train['TimeSnap'] = train['TimeSnap'].apply(lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ"))
    train['TimeDelta'] = train.apply(lambda row: (row['TimeHandoff'] - row['TimeSnap']).total_seconds(), axis=1)
    # train['date_game'] = train_single.GameId.map(lambda x: pd.to_datetime(str(x)[:8]))

    ## play是否发生在控球方所在的半场
    train['own_field'] = (train['FieldPosition'].fillna('') == train['PossessionTeam']).astype(int)
    ## 主队持球或是客队持球
    train['process_type'] = (train['PossessionTeam'] == train['HomeTeamAbbr']).astype(int)

    ## PlayDirection
    train['ToLeft'] = train.PlayDirection == "left"
    # train['PlayDirection'] = train['PlayDirection'].apply(lambda x: x.strip() == 'right')

    # 是否为防守方
    train['TeamOnOffense'] = "home"
    train.loc[train.PossessionTeam != train.HomeTeamAbbr, 'TeamOnOffense'] = "away"
    train['IsOnOffense'] = train.Team == train.TeamOnOffense  # Is player on offense?

    # 发球线离自家球门的实际码线距离
    train['YardLine'] = train.apply(
        lambda x: (x.loc['YardLine']) if x.loc['own_field'] == 1 else (100 - x.loc['YardLine']), axis=1)
    # train['dist_to_end_train'] = train.apply(lambda x: (100 - x.loc['YardLine']) if x.loc['own_field'] == 1 else x.loc['YardLine'], axis=1)
    # ? https://www.kaggle.com/bgmello/neural-networks-feature-engineering-for-the-win
    # train['dist_to_end_train'] = train.apply(lambda row: row['dist_to_end_train'] if row['PlayDirection'] else 100 - row['dist_to_end_train'],axis=1)
    # train.drop(train.index[(train['dist_to_end_train'] < train['Yards']) | (train['dist_to_end_train'] - 100 > train['Yards'])],inplace=True)

    # 统一进攻方向 https://www.kaggle.com/cpmpml/initial-wrangling-voronoi-areas-in-python
    # https://www.kaggle.com/cpmpml/initial-wrangling-voronoi-areas-in-python?scriptVersionId=22014032
    train['Dir_rad'] = np.mod(90 - train.Dir, 360) * math.pi / 180.0
    train['Ori_rad'] = np.mod(90 - train.Orientation, 360) * math.pi / 180.0
    # train['X_std'] = train.X
    train.loc[train.ToLeft, 'X'] = 120 - train.loc[train.ToLeft, 'X']
    # train['Y_std'] = train.Y
    train.loc[train.ToLeft, 'Y'] = 160 / 3 - train.loc[train.ToLeft, 'Y']
    train['Dir_std'] = train.Dir_rad
    train['Ori_std'] = train.Ori_rad
    train.loc[train.ToLeft, 'Dir_std'] = np.mod(np.pi + train.loc[train.ToLeft, 'Dir_rad'], 2 * np.pi)
    train.loc[train.ToLeft, 'Ori_std'] = np.mod(np.pi + train.loc[train.ToLeft, 'Ori_rad'], 2 * np.pi)

    # 离发球线距离x
    train['dist_yardline'] = train['YardLine'] - train['X'] / 0.91

    # 方向是否与进攻方向相同
    train['is_Dir_back'] = train['Dir_rad'].apply(lambda x: 1 if (x > np.pi) else 0)
    train['is_Ori_back'] = train['Ori_std'].apply(lambda x: 1 if (x > np.pi) else 0)
    train['Dir_std'] = train['Dir_std'].apply(lambda x: np.mod(x, np.pi))
    train['Ori_std'] = train['Ori_std'].apply(lambda x: np.mod(x, np.pi))

    # 分方向的速度
    train["Dir_std_sin"] = train["Dir_std"].apply(lambda x: np.sin(x))
    train["Dir_std_cos"] = train["Dir_std"].apply(lambda x: np.cos(x))
    train['S_horizontal'] = train['S'] * train['Dir_std_cos']
    train['S_vertical'] = train['S'] * train['Dir_std_sin']

    ## Rusher
    train['IsRusher'] = (train['NflId'] == train['NflIdRusher'])
    # train['IsRusher_ob'] = (train['NflId'] == train['NflIdRusher']).astype("object")
    # temp = train[train["IsRusher"]][["Team", "PlayId"]].rename(columns={"Team": "RusherTeam"})
    # train = train.merge(temp, on="PlayId")
    # train["IsRusherTeam"] = train["Team"] == train["RusherTeam"]

    # 球员距rusher的距离
    tmp = train[train['IsRusher'] == True][['GameId', 'PlayId', 'X', 'Y']].copy().rename(columns={'X': 'Rusher_X',
                                                                                'Y': 'Rusher_Y'})
    train = pd.merge(train, tmp, on=['GameId', 'PlayId'], how='inner')
    train['dist_to_rusher'] = train[['X', 'Y', 'Rusher_X', 'Rusher_Y']].apply(
        lambda x: euclidean_distance(x[0], x[1], x[2], x[3]), axis=1)

    # 所有球员跑向rusher需要的时间,(假设rusher不动)
    train['time_to_rusher'] = train[['X', 'Y', 'Rusher_X', 'Rusher_Y', 'S', 'A', ]].apply(
        lambda x: min_tackle_time(euclidean_distance(x[0], x[1], x[2], x[3]), x[4], x[5]), axis=1)
    # train['time_to_rusher_Defend'] = train[train['IsOnOffense'] == False][['X', 'Y','Rusher_X', 'Rusher_Y', 'S', 'A',]].apply(
    #         lambda x: min_tackle_time(euclidean_distance(x[0], x[1], x[2], x[3]), x[4], x[5]), axis=1)

    # Rusher距QB的距离，训练集23171 中有23290个QB，待确认缺失数据的处理
    QB_distance = train[train['Position'] == 'QB'][['dist_to_rusher', 'GameId', 'PlayId']].rename(
        columns={'dist_to_rusher': 'dist_QB'})
    train = pd.merge(train, QB_distance, on=['GameId', 'PlayId'], how='left')
    # print("0.3", train.shape)

    # let's say now I want for that specific play to have as features the # of players within 3, 6, 9, 12, 15
    # yards of distance from the runner. In that case, as I already have the distances from the runner to each of the 11 defense players, I will count how many of them are within each of these intervals, and return those.
    # defense_x = train[train['IsOnOffense'] == False][['X','Rusher_X','GameId','PlayId']].apply

    # 每个play对应两条,敌方球员距离，友方球员距离
    Offense_player_distance = train[(train['IsOnOffense'] == True) & (train['dist_to_rusher'] > 0)].groupby(
        ['GameId', 'PlayId']) \
        .agg({'dist_to_rusher': ['min', 'max', 'mean', 'std'],
              'X': ['mean', 'std'], 'Y': ['max', 'min', 'mean', 'std'],
              'time_to_rusher': ['mean', 'min']
              }).rename(columns={
        'min': 'Offense_min', 'max': 'Offense_max', 'mean': 'Offense_mean', 'std': 'Offense_std'}).reset_index()
    Defense_player_distance = train[train['IsOnOffense'] == False].groupby(['GameId', 'PlayId']) \
        .agg({'dist_to_rusher': ['min', 'max', 'mean', 'std'],
              'X': ['mean', 'std'], 'Y': ['mean', 'std', 'max', 'min'],
              'time_to_rusher': ['mean', 'min']
              }).reset_index()  # min表示防守方跑的最快的球员跑到rusher的时间
    player_distance = pd.merge(Offense_player_distance, Defense_player_distance, on=['GameId', 'PlayId'], how='left')
    train = pd.merge(train, player_distance, on=['GameId', 'PlayId'], how='left')
    train['defense_y_spread'] = train[('Y', 'max')] - train[('Y', 'min')]
    train['offense_y_spread'] = train[('Y', 'Offense_max')] - train[('Y', 'Offense_min')]

    # closest defense player
    closest_defense_player = train[
        (train['IsOnOffense'] == False) & (train[('dist_to_rusher', 'min')] == train['dist_to_rusher'])]
    closest_defense_player = closest_defense_player[['GameId', 'PlayId', 'S', 'A', 'Dir_std', 'Ori_std', 'Dis']].rename(
        columns={
            'S': 'closest_S', 'A': 'closest_A', 'Dir_std': 'closest_Dir', 'Ori_std': 'closest_Ord',
            'Dis': 'closest_Dis'})
    train = pd.merge(train, closest_defense_player, on=['GameId', 'PlayId'], how='left')
    train['rusher_S_closet'] = train['S'] / (train['closest_S'] + 0.001)
    train['rusher_A_closet'] = train['A'] / (train['closest_A'] + 0.001)
    train.drop(['closest_S', 'closest_A'], axis=1, inplace=True)

    # 球员距发球线的距离
    train['dist_to_yardline'] = train[['X', 'YardLine']].apply(lambda x: x[0] - x[1], axis=1)

    train['Team'] = train['Team'].apply(lambda x: x.strip() == 'home')

    ## diff Score
    train["diffScoreBeforePlay"] = train["HomeScoreBeforePlay"] - train["VisitorScoreBeforePlay"]
    # train["diffScoreBeforePlay_binary_ob"] = (train["HomeScoreBeforePlay"] > train["VisitorScoreBeforePlay"]).astype("object")

    # ——————— player ———————
    ## Age
    train['PlayerBirthDate'] = train['PlayerBirthDate'].apply(lambda x: datetime.datetime.strptime(x, "%m/%d/%Y"))
    seconds_in_year = 60 * 60 * 24 * 365.25
    train['PlayerAge'] = train.apply(
        lambda row: (row['TimeHandoff'] - row['PlayerBirthDate']).total_seconds() / seconds_in_year, axis=1)
    # train["PlayerAge_ob"] = train['PlayerAge'].astype(np.int).astype("object") # 是否要将其看成cat变量

    ## Height
    train['PlayerHeight'] = train['PlayerHeight'].apply(lambda x: 12 * int(x.split('-')[0]) + int(x.split('-')[1]))
    train['PlayerBMI'] = 703 * (train['PlayerWeight'] / (train['PlayerHeight']) ** 2)
    print(2)
    print(train.shape)
    ## Orientation and Dir
    # train["Orientation_ob"] = train["Orientation"].apply(lambda x: orientation_to_cat(x)).astype("object")
    # train["Dir_ob"] = train["Dir"].apply(lambda x: orientation_to_cat(x)).astype("object")
    #
    # train["Orientation_sin"] = train["Orientation"].apply(lambda x: np.sin(x / 360 * 2 * np.pi))
    # train["Orientation_cos"] = train["Orientation"].apply(lambda x: np.cos(x / 360 * 2 * np.pi))
    # train["Dir_sin"] = train["Dir"].apply(lambda x: np.sin(x / 360 * 2 * np.pi))
    # train["Dir_cos"] = train["Dir"].apply(lambda x: np.cos(x / 360 * 2 * np.pi))
    # train = pd.concat(
    #     [train.drop(['OffenseFormation'], axis=1), pd.get_dummies(train['OffenseFormation'], prefix='Formation')],
    #     axis=1)

    # ——————— environment ———————

    ## Weather
    train['GameWeather_process'] = train['GameWeather'].str.lower()
    train['GameWeather_process'] = train['GameWeather_process'].apply(
        lambda x: "indoor" if not pd.isna(x) and "indoor" in x else x)
    train['GameWeather_process'] = train['GameWeather_process'].apply(
        lambda x: x.replace('coudy', 'cloudy').replace('clouidy', 'cloudy').replace('party', 'partly') if not pd.isna(
            x) else x)
    train['GameWeather_process'] = train['GameWeather_process'].apply(
        lambda x: x.replace('clear and sunny', 'sunny and clear') if not pd.isna(x) else x)
    train['GameWeather_process'] = train['GameWeather_process'].apply(
        lambda x: x.replace('skies', '').replace("mostly", "").strip() if not pd.isna(x) else x)
    train['GameWeather_dense'] = train['GameWeather_process'].apply(map_weather)

    ## WindSpeed
    # print(train['WindSpeed'].value_counts())
    # train['WindSpeed_ob'] = train['WindSpeed'].apply(
    #     lambda x: x.lower().replace('mph', '').strip() if not pd.isna(x) else x)
    # train['WindSpeed_ob'] = train['WindSpeed_ob'].apply(
    #     lambda x: (int(x.split('-')[0]) + int(x.split('-')[1])) / 2 if not pd.isna(x) and '-' in x else x)
    # train['WindSpeed_ob'] = train['WindSpeed_ob'].apply(
    #     lambda x: (int(x.split()[0]) + int(x.split()[-1])) / 2 if not pd.isna(x) and type(
    #         x) != float and 'gusts up to' in x else x)
    # train['WindSpeed_dense'] = train['WindSpeed_ob'].apply(strtofloat)

    ## Turf
    # Turf = {'Field Turf': 'Artificial', 'A-Turf Titan': 'Artificial', 'Grass': 'Natural',
    #         'UBU Sports Speed S5-M': 'Artificial', 'Artificial': 'Artificial', 'DD GrassMaster': 'Artificial',
    #         'Natural Grass': 'Natural', 'UBU Speed Series-S5-M': 'Artificial', 'FieldTurf': 'Artificial',
    #         'FieldTurf 360': 'Artificial', 'Natural grass': 'Natural', 'grass': 'Natural', 'Natural': 'Natural',
    #         'Artifical': 'Artificial', 'FieldTurf360': 'Artificial', 'Naturall Grass': 'Natural',
    #         'Field turf': 'Artificial', 'SISGrass': 'Artificial', 'Twenty-Four/Seven Turf': 'Artificial',
    #         'natural grass': 'Natural'}
    # train['Turf'] = train['Turf'].map(Turf)
    grass_labels = ['grass', 'natural grass', 'natural', 'naturall grass']
    train['Grass'] = np.where(train.Turf.str.lower().isin(grass_labels), 1, 0)

    # StadiumType
    train['StadiumType'] = train['StadiumType'].apply(clean_StadiumType)
    train['StadiumType'] = train['StadiumType'].apply(transform_StadiumType)

    # ——————— after possess ———————
    print(3)
    print(train.shape)

    ## sort
    # train = train.sort_values(by=['X']).sort_values(by=['Dis']).sort_values(by=['PlayId']).reset_index(drop=True)
    # train = train.sort_values(by=['X']).sort_values(by=['Dis']).sort_values(by=['PlayId', 'IsRusherTeam', 'IsRusher']).reset_index(drop=True)
    # pd.to_pickle(train, "train.pkl")

    ## dense -> categorical
    train["Quarter"] = train["Quarter"].astype("object")
    train["Down"] = train["Down"].astype("object")
    train["JerseyNumber"] = train["JerseyNumber"].astype("object")
    train["OffenseFormation"] = train["OffenseFormation"].astype("object")
    # train["YardLine_ob"] = train["YardLine"].astype("object")
    # train["DefendersInTheBox_ob"] = train["DefendersInTheBox"].astype("object")
    train["Week"] = train["Week"].astype("object")
    # train["TimeDelta_ob"] = train["TimeDelta"].astype("object")
    # train["HomeTeamAbbr"] = train["HomeTeamAbbr"].astype("object")
    # train["VisitorTeamAbbr"] = train["VisitorTeamAbbr"].astype("object")

    train = train[train['IsRusher'] == True]  # 树模型中目前只处理rusher
    print(train.shape)

    ## OffensePersonnel
    temp = train[train['IsRusher'] == True]["OffensePersonnel"].apply(
        lambda x: pd.Series(OffensePersonnelSplit(x))).reset_index()
    temp.columns = ["Offense" + c for c in temp.columns]
    temp["PlayId"] = train["PlayId"]
    print(temp.shape)
    train = train.merge(temp, on="PlayId", how='left')
    print(train.shape)
    ## DefensePersonnel
    temp = train[train['IsRusher'] == True]["DefensePersonnel"].apply(
        lambda x: pd.Series(DefensePersonnelSplit(x))).reset_index()
    temp.columns = ["Defense" + c for c in temp.columns]
    temp["PlayId"] = train["PlayId"]
    train = train.merge(temp, on="PlayId", how='left')

    print(4)
    print(train.shape)

    drop(train)

    train.fillna(-999, inplace=True)

    print("feature process end,with feature shape:", train.shape)
    # print(train)

    return train

class Metric(Callback):
    def __init__(self, model, callbacks, data):
        super().__init__()
        self.model = model
        self.callbacks = callbacks
        self.data = data

    def on_train_begin(self, logs=None):
        for callback in self.callbacks:
            callback.on_train_begin(logs)

    def on_train_end(self, logs=None):
        for callback in self.callbacks:
            callback.on_train_end(logs)

    def on_epoch_end(self, batch, logs=None):
        X_train, y_train = self.data[0][0], self.data[0][1]
        y_pred = self.model.predict(X_train)
        y_true = np.clip(np.cumsum(y_train, axis=1), 0, 1)
        y_pred = np.clip(np.cumsum(y_pred, axis=1), 0, 1)
        tr_s = ((y_true - y_pred) ** 2).sum(axis=1).sum(axis=0) / (199 * X_train.shape[0])
        tr_s = np.round(tr_s, 6)
        logs['tr_CRPS'] = tr_s

        X_valid, y_valid = self.data[1][0], self.data[1][1]

        y_pred = self.model.predict(X_valid)
        y_true = np.clip(np.cumsum(y_valid, axis=1), 0, 1)
        y_pred = np.clip(np.cumsum(y_pred, axis=1), 0, 1)
        val_s = ((y_true - y_pred) ** 2).sum(axis=1).sum(axis=0) / (199 * X_valid.shape[0])
        val_s = np.round(val_s, 6)
        logs['val_CRPS'] = val_s
        print('tr CRPS', tr_s, 'val CRPS', val_s)

        for callback in self.callbacks:
            callback.on_epoch_end(batch, logs)

# if __name__ == '__main__':

# train = pd.read_csv('../data/train.csv')
train = pd.read_csv('../input/nfl-big-data-bowl-2020/train.csv')
train_basetable = preprocess(train)

yards = train_basetable.pop('Yards')

y = np.zeros((yards.shape[0], 199))
for idx, target in enumerate(list(yards)):
    y[idx][99 + target] = 1

cat_features = []
dense_features = []
sss = {}
lbls = {}
X_train = train_basetable
for col in X_train.columns:
    if X_train[col].dtype == 'object':
        # print(f)
        cat_features.append((col, len(train[col].unique())))
        lbl = LabelEncoder()
        X_train[col].fillna(-999, inplace=True)
        lbl.fit(list(X_train[col]) + [-999])
        X_train[col] = lbl.transform(list(X_train[col]))
        dic = dict(zip(lbl.classes_, lbl.transform(lbl.classes_)))
        lbls[col] = dic
    else:
        ss = StandardScaler()
        X_train[col].fillna(np.mean(X_train[col]), inplace=True)
        X_train.loc[:, col] = ss.fit_transform(X_train[col].values[:, None])
        dense_features.append(col)
        sss[col] = ss
dense_features.remove('GameId')
X = X_train
inputs = []
embeddings = []
for i in cat_features:
    input_ = Input(shape=(1,))
    embedding = Embedding(int(np.absolute(X[i]).max() + 1), 10, input_length=1)(input_)
    embedding = Reshape(target_shape=(10,))(embedding)
    inputs.append(input_)
    embeddings.append(embedding)
input_numeric = Input(shape=(len(dense_features),))
embedding_numeric = Dense(512, activation='relu')(input_numeric)
inputs.append(input_numeric)
embeddings.append(embedding_numeric)
x = Concatenate()(embeddings)
x = Dense(256, activation='relu')(x)
x = Dense(128, activation='relu')(x)
x = Dropout(0.5)(x)
output = Dense(199, activation='softmax')(x)
model = Model(inputs, output)

n_splits = 5
kf = GroupKFold(n_splits=n_splits)
score = []
models = []
for i_369, (tdx, vdx) in enumerate(kf.split(X, y, X['GameId'])):
    print(f'Fold : {i_369}')
    X_train, X_val, y_train, y_val = X.iloc[tdx], X.iloc[vdx], y[tdx], y[vdx]
    X_train = [np.absolute(X_train[i]) for i in cat_features] + [X_train[dense_features]]
    X_val = [np.absolute(X_val[i]) for i in cat_features] + [X_val[dense_features]]
    model.compile(optimizer='Adam', loss='categorical_crossentropy', metrics=[])
    es = EarlyStopping(monitor='val_CRPS',
                       mode='min',
                       restore_best_weights=True,
                       verbose=2,
                       patience=5)
    es.set_model(model)
    metric = Metric(model, [es], [(X_train, y_train), (X_val, y_val)])
    for i in range(1):
        model.fit(X_train, y_train, verbose=False)
    for i in range(1):
        model.fit(X_train, y_train, batch_size=64, verbose=False)
    for i in range(1):
        model.fit(X_train, y_train, batch_size=128, verbose=False)
    for i in range(1):
        model.fit(X_train, y_train, batch_size=256, verbose=False)
    model.fit(X_train, y_train, callbacks=[metric], epochs=100, batch_size=1024, verbose=False)
    score_ = crps(y_val, model.predict(X_val))
    # model.save(f'keras_369_{i_369}.h5')
    models.append(model)
    print(score_)
    score.append(score_)

print(np.mean(score))

from kaggle.competitions import nflrush

env = nflrush.make_env()
iter_test = env.iter_test()
for (test_df, sample_prediction_df) in iter_test:
    X_test = preprocess(test_df)
    for col in X_test.columns:
        if X_test[col].dtype == 'object':
            # print(f)
            # X_test[col] = lbls[col].transform(list(X_test[col]))
            X_test[col] = X_test[col].map(lbls[col]).fillna(0).astype(int)
        else:
            X_test.loc[:, col] = sss[col].transform(X_test[col].values[:, None])

    y_pred = np.mean([model.predict(X_test) for model in models], axis=0)

    y_pred = np.clip(np.cumsum(y_pred, axis=1), 0, 1).tolist()[0]

    preds_df = pd.DataFrame(data=[y_pred], columns=sample_prediction_df.columns)
    preds_df.iloc[:, :50] = 0
    preds_df.iloc[:, -50:] = 1
    env.predict(preds_df)

env.write_submission_file()


# 4. Пользователь вводит целое положительное число.
# Найдите самую большую цифру в числе.
# Для решения используйте цикл while и арифметические операции.

# Вычисления
# 2354 % 10
# 4
# 2354 - 4
# 2350
# 2350 / 10

# Проверил на числе 2354 получил 5
# Проверил на числе 12349857659 получил число 9

positive_number = int(input("Введи целое положительное число - "))

max_number = 0

while positive_number != 0:
    remainder = positive_number % 10

    if max_number < remainder:
        max_number = remainder

    positive_number = positive_number - remainder
    positive_number //= 10

print(f"Максимальное число: {max_number}")


import threading
import socket
import time
import sys

# Messaging Port = 8080
# Controlling Port = 7070

# This lock is needed to ensure that the client thread is
# created after the initial start signal of the r2 node.
lock = threading.Lock()
# RTTs of the edges from r1 to s and d.
rtts = {"s": 0, "d": 0}

def server(ip, port):
    """
    Server thread implementation.
    It directly sends back the received packet.
    Args:
        ip: IP of the machine that is connected
            to the corresponding client program.
        port: Port number that is connected to
              the corresponding client program.
    """
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    server_socket.bind((ip, port))
    server_socket.recvfrom(1024)
    lock.release()# Ready to serve release the lock
    while True:
        packet, addr = server_socket.recvfrom(1024)
        server_socket.sendto(packet, addr)

def client(name, ip, port, N):
    """
    Client thread implementation.
    It sends N messages to the (ip, port).
    Args:
        name: Name of the node to which the packets will sent.
              This name is used for the rtts dictionary.
        ip: IP of the server machine.
        port: Port number used by the server machine.
        N: Number of samples for predicting RTT.
    """
    global rtts
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    dummy_packet = ".".encode()# A dummy packet to send
    for i in range(N):
        start = time.time()# Start measuring time
        client_socket.sendto(dummy_packet, (ip, port))
        client_socket.recvfrom(1024)
        end = time.time()# Stop measuring time
        rtts[name] += (end - start)# Accumulate each sampled RTT
    rtts[name] /= N# Average accumulated RTTs

def main():
    """
    Main function initializing the threads and killing them at the end.
    """
    global rtts
    N = int(sys.argv[1])
    lock.acquire()# Hold lock until the server is ready to serve
    t_server = threading.Thread(target=server, args=("10.10.4.1", 8080))
    t_server.daemon = True# This ensures that the server thread will be killed after main is done
    t_server.start()
    lock.acquire()# Wait for the server thread to get ready to serve
    lock.release()# The server thread is ready we are done with the lock
    t_client_s = threading.Thread(target=client, args=("s", "10.10.1.1", 8080, N))
    t_client_d = threading.Thread(target=client, args=("d", "10.10.4.2", 8080, N))
    t_client_s.start()
    t_client_d.start()
    t_client_s.join()
    t_client_d.join()
    f = open("link_costs.txt", "w+")# Write results to the file
    for i in rtts:
        out = "r1-" + i + " = " + str(rtts[i])
        f.write(out + "\n")
        print(out)
    f.close()
    termination_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    termination_socket.bind(("10.10.4.1", 7070))
    termination_socket.sendto("!".encode(), ("10.10.5.1", 7070))# Let r2 know that you are done with measuring
    termination_socket.recvfrom(1024)# Wait for r2 to inform you that you and the server thread can die in peace

main()


from unittest.mock import patch

import app.views.index

class MockMD5(object):

    def __init__(self, return_value):
        self._return_value = return_value

    def hexdigest(self):
        return self._return_value

def test_index(client):
    expected_version = "1234567890"
    expected_value = "favicon.ico?version={}".format(expected_version)

    with patch.object(app.views.index, "md5", return_value=MockMD5(expected_version)):
        with open("app/templates/index.html", "rb") as template:
            expected_body = template.read().replace(bytes("{{ icon }}", encoding="utf-8"),
                                                    bytes(expected_value, encoding="utf-8"))
            assert client.get("/").status_code == 200
            assert client.get("/").get_data() == expected_body

def test_favicon(client):
    with open("favicon.ico", "rb") as icon:
        assert client.get("/favicon.ico").status_code == 200
        assert client.get("/favicon.ico").get_data() == icon.read()


from pyformance import MetricsRegistry
from wavefront_pyformance.wavefront_reporter import WavefrontReporter, WavefrontProxyReporter, WavefrontDirectReporter
from wavefront_pyformance import delta
import time
import sys

def report_metrics(host, server, token):
    reg = MetricsRegistry()

    wf_proxy_reporter = WavefrontProxyReporter(host=host, port=2878, registry=reg, source="wavefront-pyformance-example", tags={"key1":"val1", "key2":"val2"}, prefix="python.proxy.")
    wf_direct_reporter = WavefrontDirectReporter(server=server, token=token, registry=reg, source="wavefront-pyformance-exmaple", tags={"key1":"val1", "key2": "val2"}, prefix="python.direct.")

    # counter
    c1 = reg.counter("foo_count")
    c1.inc()

    # delta counter
    d1 = delta.delta_counter(reg, "foo_delta_count")
    d1.inc()
    d1.inc()

    # gauge
    g1 = reg.gauge("foo_gauge")
    g1.set_value(2)

    # meter
    m1 = reg.meter("foo_meter")
    m1.mark()

    # timer
    t1 = reg.timer("foo_timer")
    timer_ctx = t1.time()
    time.sleep(3)
    timer_ctx.stop()

    # histogram
    h1 = reg.histogram("foo_histogram")
    h1.add(1.0)
    h1.add(1.5)

    wf_proxy_reporter.report_now()
    wf_proxy_reporter.stop()
    wf_direct_reporter.report_now()

if __name__ == "__main__":
    # python example.py proxy_host server_url server_token
    host = sys.argv[1]
    server = sys.argv[2]
    token = sys.argv[3]
    report_metrics(host, server, token)


# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Partial implementation for Swift dylib processing for bundles."""

load(
    "@bazel_skylib//lib:collections.bzl",
    "collections",
)
load(
    "@bazel_skylib//lib:partial.bzl",
    "partial",
)
load(
    "@bazel_skylib//lib:paths.bzl",
    "paths",
)
load(
    "@build_bazel_rules_apple//apple/bundling:platform_support.bzl",
    "platform_support",
)
load(
    "@build_bazel_rules_apple//apple/bundling:swift_support.bzl",
    "swift_support",
)
load(
    "@build_bazel_rules_apple//apple/bundling/experimental:intermediates.bzl",
    "intermediates",
)
load(
    "@build_bazel_rules_apple//apple/bundling/experimental:processor.bzl",
    "processor",
)
load(
    "@build_bazel_rules_apple//apple:utils.bzl",
    "xcrun_action",
)

_AppleSwiftDylibsInfo = provider(
    doc = """
Private provider to propagate the transitive binary `File`s that depend on
Swift.
""",
    fields = {
        "binary": """
Depset of binary `File`s containing the transitive dependency binaries that use
Swift.
""",
    },
)

def _swift_dylib_action(ctx, platform_name, binary_files, output_dir):
    """Registers a swift-stlib-tool action to gather Swift dylibs to bundle."""
    args = [
        "swift-stdlib-tool",
        "--copy",
        "--destination",
        output_dir.path,
        "--platform",
        platform_name,
    ] + collections.before_each("--scan-executable", [
        x.path
        for x in binary_files
    ])

    xcrun_action(
        ctx,
        inputs = binary_files,
        outputs = [output_dir],
        arguments = args,
        mnemonic = "SwiftStdlibCopy",
        no_sandbox = True,
    )

def _swift_dylibs_partial_impl(ctx, binary_artifact, dependency_targets, package_dylibs):
    """Implementation for the Swift dylibs processing partial."""
    transitive_binaries = depset(transitive = [
        x[_AppleSwiftDylibsInfo].binary
        for x in dependency_targets
    ])

    if swift_support.uses_swift(ctx.attr.deps):
        transitive_binaries = depset(
            [binary_artifact],
            transitive = [transitive_binaries],
        )

    bundle_files = []
    if package_dylibs:
        # TODO(kaipi): Handle multiple platforms in the same build (i.e.
        # watchos_application targets)
        platform_name = platform_support.platform(ctx).name_in_plist.lower()
        output_dir = intermediates.directory(
            ctx.actions,
            ctx.label.name,
            "swiftlibs",
        )
        _swift_dylib_action(
            ctx,
            platform_name,
            transitive_binaries.to_list(),
            output_dir,
        )

        bundle_files.append(
            (processor.location.framework, None, depset([output_dir])),
        )

        # TODO(kaipi): Revisit if we can add this only for non enterprise optimized
        # builds, or at least only for device builds.
        swift_support_path = paths.join("SwiftSupport", platform_name)
        bundle_files.append(
            (processor.location.archive, swift_support_path, depset([output_dir])),
        )

    return struct(
        bundle_files = bundle_files,
        providers = [_AppleSwiftDylibsInfo(binary = transitive_binaries)],
    )

def swift_dylibs_partial(binary_artifact, dependency_targets = [], package_dylibs = False):
    """Constructor for the Swift dylibs processing partial.

    This partial handles the Swift dylibs that may need to be packaged or propagated.

    Args:
      binary_artifact: The main binary artifact for this target.
      dependency_targets: List of targets that should be checked for binaries that might contain
        Swift, so that the Swift dylibs can be collected.
      package_dylibs: Whether the partial should return the Swift files to be packaged inside the
        target's bundle.

    Returns:
      A partial that returns the bundle location of the Swift dylibs, if there were any to bundle.
    """
    return partial.make(
        _swift_dylibs_partial_impl,
        binary_artifact = binary_artifact,
        dependency_targets = dependency_targets,
        package_dylibs = package_dylibs,
    )


class PIDController:
    """
    PID controller implementation.
    """

    COOLDOWN = 5

    def __init__(self, kp=16.5, ki=1.07, kd=0.0):
        """
        :param kp: Weight of proportional factor
        :param ki: Weight of integral factor
        :param kd: Weight of differential factor
        """
        self.kp = kp
        self.ki = ki
        self.kd = kd

        self._accumulated_error = 0.0
        self._previous_error = 0.0

    def control(self, error):
        """
        Obtain correction factor.

        :param error: Accumulated error since last invocation
        :return: Correction factor
        """
        self._accumulated_error = self._accumulated_error + error

        ret =  self.kp * error + \
               self.ki * self._accumulated_error + \
               self.kd * (error - self._previous_error)

        self._previous_error = error

        return ret


#
# created by
# Antonio Garcia-Uceda Juarez
# PhD student
# Medical Informatics
#
# created on 09/02/2018
# Last update: 09/02/2018
########################################################################################

from CommonUtil.ErrorMessages import *
from CommonUtil.FunctionsUtil import *
import SimpleITK as sitk
import pydicom
from pydicom.dataset import Dataset, FileDataset
import nibabel as nib
import numpy as np
import h5py
import datetime, time
import gzip

class GZIPmanager(object):

    @staticmethod
    def getReadFile(filename):
        return gzip.GzipFile(filename, 'r')

    @staticmethod
    def getWriteFile(filename):
        return gzip.GzipFile(filename, 'w')

    @staticmethod
    def closeFile(fileobj):
        fileobj.close()

class FileReader(object):

    @staticmethod
    def getImageSize(filename):

        basename, extension = ospath_splitext_recurse(filename)

        if (extension == '.dcm'):
            return DICOMreader.getImageSize(filename)
        if (extension == '.dcm.gz'):
            print("Not implemented for extension '.dcm.gz'...")
            return False
            # fileobj = GZIPmanager.getReadFile(filename)
            # out_arrsize = DICOMreader.getImageSize(fileobj)
            # GZIPmanager.closeFile(fileobj)
            # return out_arrsize
        elif (extension == '.nii'):
            return NIFTIreader.getImageSize(filename)
        elif (extension == '.nii.gz'):
            return NIFTIreader.getImageSize(filename)
        elif (extension == '.npy'):
            return NUMPYreader.getImageSize(filename)
        elif (extension == '.npz'):
            return NUMPYZreader.getImageSize(filename)
        elif (extension == '.npy.gz'):
            fileobj = GZIPmanager.getReadFile(filename)
            out_arrsize = NUMPYreader.getImageSize(fileobj)
            GZIPmanager.closeFile(fileobj)
            return out_arrsize
        elif (extension == '.hdf5'):
            return HDF5reader.getImageSize(filename)
        else:
            message = "No valid file extension: %s..." %(extension)
            CatchErrorException(message)

    @staticmethod
    def getImageArray(filename):

        basename, extension = ospath_splitext_recurse(filename)

        if (extension == '.dcm'):
            return DICOMreader.getImageArray(filename)
        if (extension == '.dcm.gz'):
            print("Not implemented for extension '.dcm.gz'...")
            return False
            # fileobj = GZIPmanager.getReadFile(filename)
            # out_array = DICOMreader.getImageArray(fileobj)
            # GZIPmanager.closeFile(fileobj)
            # return out_array
        elif (extension == '.nii'):
            return NIFTIreader.getImageArray(filename)
        elif (extension == '.nii.gz'):
            return NIFTIreader.getImageArray(filename)
        elif (extension == '.npy'):
            return NUMPYreader.getImageArray(filename)
        elif (extension == '.npz'):
            return NUMPYZreader.getImageArray(filename)
        elif (extension == '.npy.gz'):
            fileobj = GZIPmanager.getReadFile(filename)
            out_array = NUMPYreader.getImageArray(fileobj)
            GZIPmanager.closeFile(fileobj)
            return out_array
        elif (extension == '.hdf5'):
            return HDF5reader.getImageArray(filename)
        else:
            message = "No valid file extension: %s..." %(extension)
            CatchErrorException(message)

    @staticmethod
    def writeImageArray(filename, image_array):

        basename, extension = ospath_splitext_recurse(filename)

        if (extension == '.dcm'):
            DICOMreader.writeImageArray(filename, image_array)
        if (extension == '.dcm.gz'):
            print("Not implemented for extension '.dcm.gz'...")
            return False
            # fileobj = GZIPmanager.getWriteFile(filename)
            # DICOMreader.writeImageArray(fileobj, image_array)
            # GZIPmanager.closeFile(fileobj)
        elif (extension == '.nii'):
            NIFTIreader.writeImageArray(filename, image_array)
        elif (extension == '.nii.gz'):
            NIFTIreader.writeImageArray(filename, image_array)
        elif (extension == '.npy'):
            NUMPYreader.writeImageArray(filename, image_array)
        elif (extension == '.npz'):
            NUMPYZreader.writeImageArray(filename, image_array)
        elif (extension == '.npy.gz'):
            fileobj = GZIPmanager.getWriteFile(filename)
            NUMPYreader.writeImageArray(fileobj, image_array)
            GZIPmanager.closeFile(fileobj)
        elif (extension == '.hdf5'):
            HDF5reader.writeImageArray(filename, image_array)
        else:
            message = "No valid file extension: %s..." %(extension)
            CatchErrorException(message)

class HDF5reader(FileReader):

    # get h5py image size:
    @staticmethod
    def getImageSize(filename):
        data_file = h5py.File(filename, 'r')
        return data_file['data'].shape

    # get h5py image array:
    @staticmethod
    def getImageArray(filename):
        data_file = h5py.File(filename, 'r')
        return data_file['data'][:]

    # write h5py file array:
    @staticmethod
    def writeImageArray(filename, image_array):
        data_file = h5py.File(filename, 'w')
        data_file.create_dataset('data', data=image_array)
        data_file.close()

class NUMPYreader(FileReader):

    # get numpy image size:
    @staticmethod
    def getImageSize(filename):
        return np.load(filename).shape

    # get numpy image array:
    @staticmethod
    def getImageArray(filename):
        return np.load(filename)

    # write numpy file array:
    @staticmethod
    def writeImageArray(filename, image_array):
        np.save(filename, image_array)

class NUMPYZreader(FileReader):

    # get numpy image size:
    @staticmethod
    def getImageSize(filename):
        return np.load(filename)['arr_0'].shape

    # get numpy image array:
    @staticmethod
    def getImageArray(filename):
        return np.load(filename)['arr_0']

    # write numpy file array:
    @staticmethod
    def writeImageArray(filename, image_array):
        np.savez_compressed(filename, image_array)

class NIFTIreader(FileReader):
    # In nifty format, the axes are reversed.
    # Need to swap axis and set depth_Z first dim

    # get nifti image size:
    @staticmethod
    def getImageSize(filename):
        nib_im = nib.load(filename)
        return nib_im.get_data().shape[::-1]

    # get nifti image array:
    @staticmethod
    def getImageArray(filename):
        nib_im = nib.load(filename)
        return np.swapaxes(nib_im.get_data(), 0, 2)

    # write nifti file array:
    @staticmethod
    def writeImageArray(filename, image_array):
        nib_im = nib.Nifti1Image(np.swapaxes(image_array, 0, 2), np.eye(4))
        nib.save(nib_im, filename)

class DICOMreader(FileReader):

    # get dcm image dims:
    @staticmethod
    def getImageSize(filename):
        ds = sitk.ReadImage(filename)
        #np.swapaxes(ds.GetSize(), 0, 2)
        return sitk.GetArrayFromImage(ds).shape

    # get dcm voxel size:
    @staticmethod
    def getImageVoxelSize(filename):
        ds = pydicom.read_file(filename)
        voxel_size = (float(ds.PixelSpacing[0]),
                      float(ds.PixelSpacing[1]),
                      float(ds.SpacingBetweenSlices))
        return voxel_size

    # load dcm file array:
    @staticmethod
    def getImageArray(filename):
        ds = sitk.ReadImage(filename)
        return sitk.GetArrayFromImage(ds)

    # write dcm file array:
    @staticmethod
    def writeImageArray(filename, image_array):
        ds = sitk.GetImageFromArray(image_array)
        sitk.WriteImage(ds, filename)

    @staticmethod
    def writeDICOMimage(filename, image_array):

        ## This code block was taken from the output of a MATLAB secondary
        ## capture.  I do not know what the long dotted UIDs mean, but
        ## this code works.
        file_meta = Dataset()
        file_meta.MediaStorageSOPClassUID = 'Secondary Capture Image Storage'
        file_meta.MediaStorageSOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780'
        file_meta.ImplementationClassUID = '1.3.6.1.4.1.9590.100.1.0.100.4.0'

        ds = FileDataset(filename, {}, file_meta=file_meta, preamble="\0" * 128)
        ds.Modality = 'WSD'
        ds.ContentDate = str(datetime.date.today()).replace('-', '')
        ds.ContentTime = str(time.time())  # milliseconds since the epoch
        ds.StudyInstanceUID = '1.3.6.1.4.1.9590.100.1.1.124313977412360175234271287472804872093'
        ds.SeriesInstanceUID = '1.3.6.1.4.1.9590.100.1.1.369231118011061003403421859172643143649'
        ds.SOPInstanceUID = '1.3.6.1.4.1.9590.100.1.1.111165684411017669021768385720736873780'
        ds.SOPClassUID = 'Secondary Capture Image Storage'
        ds.SecondaryCaptureDeviceManufctur = 'Python 2.7.3'

        ## These are the necessary imaging components of the FileDataset object.
        ds.SamplesPerPixel = 1
        ds.PhotometricInterpretation = "MONOCHROME2"
        ds.PixelRepresentation = 0
        ds.HighBit = 15
        ds.BitsStored = 16
        ds.BitsAllocated = 16
        ds.SmallestImagePixelValue = '\\x00\\x00'
        ds.LargestImagePixelValue = '\\xff\\xff'
        ds.Rows = image_array.shape[0]
        ds.Columns = image_array.shape[1]
        if image_array.dtype != np.uint16:
            image_array = image_array.astype(np.uint16)
        ds.PixelData = image_array.tostring()

        ds.save_as(filename)

    # get dcm header info:
    @staticmethod
    def loadPatientInformation(filename):

        ds = pydicom.read_file(filename)

        information = {}
        information['PatientID'] = ds.PatientID
        information['PatientName'] = ds.PatientName
        information['PatientBirthDate'] = ds.PatientBirthDate
        information['PatientSex'] = ds.PatientSex
        information['StudyID'] = ds.StudyID
        # information['StudyTime'] = ds.Studytime
        information['InstitutionName'] = ds.InstitutionName
        information['Manufacturer'] = ds.Manufacturer
        information['NumberOfFrames'] = ds.NumberOfFrames
        return information

    # copy PixelData info and save image
    @staticmethod
    def copyPixelDataAndSaveImage(origfilename, newfilename):

        orig_ds = pydicom.read_file(origfilename)
        new_ds  = pydicom.read_file(newfilename)
        orig_ds.PixelData = new_ds.PixelData
        orig_ds.save_as(origfilename)

# All Available File Readers
DICTAVAILFILEREADERS = {"numpy": NUMPYreader,
                        "dicom": DICOMreader,
                        "nifti": NIFTIreader }


from django.test import TestCase
from collegeconnect.models import Student, University

class StudentTestCase(TestCase):
    def setUp(self):
        self.peter_pan = Student.objects.create(first_name="Peter", last_name="Pan")
        self.tinker_bell = Student.objects.create(first_name="Tinker", last_name="Bell")

        self.harvard =  University.objects.create(name='Harvard College', short_name='Harvard')
        self.yale = University.objects.create(name='Yale University', short_name='Yale')

    def test_applied_university_deletion(self):
        """
            Test that deleting a university removes it from the student's application list
        """
        self.tinker_bell.applied_universities.add(self.harvard, self.yale)
        self.assertEqual(len(self.tinker_bell.applied_universities.all()), 2)

        self.yale.delete()
        self.assertEqual(len(self.tinker_bell.applied_universities.all()), 1)

    def test_accepted_university_deletion(self):
        """
            Test that deleting a university removes it from the student's accepted list
        """
        self.peter_pan.accepted_universities.add(self.harvard, self.yale)
        self.assertEqual(len(self.peter_pan.accepted_universities.all()), 2)

        self.harvard.delete()
        self.assertEqual(len(self.peter_pan.accepted_universities.all()), 1)


import os
from os.path import abspath
from pathlib import Path

import pytest
from click.testing import CliRunner

from sst import cli
from tests.path_utils import get_tests_dir

STATIC_FILES = Path(get_tests_dir() + os.sep + 'static')

example_input = abspath(STATIC_FILES / "trivial_mapping_md_code_md.py")

@pytest.fixture
def cli_runner_instance():
    return CliRunner()

@pytest.mark.parametrize("type, expected_extension",
                         [('purepython', '.py'), ('markdown', '.md'), ('jupyter', '.ipynb')])
@pytest.mark.parametrize("output_filename", ['filename', 'nested/path/filename'])
def test_cli_positive(cli_runner_instance, tmp_path, type, expected_extension, output_filename):
    outfile_path = tmp_path / output_filename
    expected_output_path = Path(str(outfile_path) + expected_extension)

    result = cli_runner_instance.invoke(cli, ['--source', example_input, "--output", outfile_path, "--type", type])

    if result.exception:
        print(result.exception)

    assert result.exit_code == 0
    assert os.path.exists(expected_output_path)

def test_py_file_with_import(cli_runner_instance, tmp_path):
    file_path = STATIC_FILES / 'py_with_import.py'
    expected_markdown_path = STATIC_FILES / 'py_with_import.md'

    outfile = tmp_path / 'output'
    outfile_path = tmp_path / 'output.md'
    result = cli_runner_instance.invoke(cli, [
        '--source', file_path, "--output", outfile, "--type", "markdown", "--execute"
    ])

    if result.exception:
        print(result.exception)

    assert result.exit_code == 0

    generated_markdown = outfile_path.read_text()
    expected_markdown = expected_markdown_path.read_text()

    assert generated_markdown == expected_markdown

def test_wrong_path_when_purepython():
    with pytest.raises(AttributeError) as e_info:
        cli_runner_instance.invoke(cli, ['--source', example_input, "--output", example_input, "--type", 'purepython'])

def test_cli_missing_filename(cli_runner_instance):
    result = cli_runner_instance.invoke(cli, ["--output", 'filename'])
    assert result.exit_code == 2

def test_cli_missing_output(cli_runner_instance):
    result = cli_runner_instance.invoke(cli, ['--source', example_input])
    assert result.exit_code == 2


import h5py
import numpy as np
import pickle
import scipy
import time
import os
import process
from os import listdir
from os.path import isfile, join
import clustering as clr
import denoising as dns

# %%

def means_vars(CODE, PATH_IN, PATH_OUT):
    """ Performs the entire preprocessing pipeline over a single hdf5 file.
    WARNING: When file dimension is huge, memory error occurs.
    """
    # IMPORTING FILE
    hdf = h5py.File(PATH_IN+'target'+CODE+'.hdf5','r')

    x = np.array(hdf['radar'])
    n_frame = x.shape[0]

    r = process.range_doppler(x[0])
    dim = r.shape

    rda = np.empty((n_frame, dim[0], dim[1]))

    for ind in range(n_frame):
        rd = process.range_doppler(x[ind])
        rda[ind, :, :] = np.array(20 * np.log10(rd))
        rda -= np.amax(rda)
        #rd[rd < -45] = -45

    print('RDA:\t\t DONE')

    # DYNAMIC THRESHOLDING
    rda_thresh_g = np.empty((n_frame, dim[0], dim[1]))

    for i in range(n_frame):
        X = rda[0,:,:].flatten()
        m = np.mean(X) + 2*np.std(X)
        rda_thresh_g[i, :, :] = (rda[i,:,:]>m)*1

    print('Thresholding:\t DONE')

    # LINE REMOVING
    rda_bool = np.empty((n_frame, dim[0], dim[1]))

    for i in range(n_frame):
        rda_bool[i,:,:] = dns.remove_line(rda_thresh_g[i,:,:], tickness=0)
        #rda_bool[i,:,:] = remove_line(rda_thresh_g[i,:,:], axis=1, tickness=0)

    print('Line Removing:\t DONE')

    # CLUSTERING
    means_true = np.empty((n_frame, 3))
    # means_noise = np.empty((n_frame, 3))
    vars_true = np.empty((n_frame, 2))

    for ind in range(n_frame):

        data = dns.select_points(rda_bool[ind], rda[ind])
        labels, m = clr.gaussian_mixtures(data, n_cluster_=2, Verbose=False, Bayesian=False)

        i_true = np.argmax(np.array(m)[:, 2])
        means_true[ind, :] = np.array(m)[i_true, :]
        primo = np.std(data[labels==i_true][:,1])
        secondo = np.std(data[labels==i_true][:,2])
        vars_true[ind, :] = np.array([primo, secondo])

    print('Clustering:\t DONE')

    with open(PATH_OUT+'means_vars'+CODE+'.p', 'wb') as outfile:
        pickle.dump((means_true, vars_true), outfile)

    print('Saving Data:\t DONE')
    print('')

# %%

# For each file in PATH_IN directory, means_vars() is applied
# every file name needs to be formatted as target+CODE+.hdf5
PATH_IN = '/Users/orientamento/Desktop/idrad/train copy/'
PATH_OUT = '/Users/orientamento/Desktop/idrad/means_vars_finale/'

# os.system('ls '+ PATH_IN + ' > list.txt')
# f = open("list.txt", "r")
#files = [(f, os.path.getsize(PATH_IN+f)) for f in listdir(PATH_IN) if isfile(join(PATH_IN, f))]
#files = [f for f, size in files if size <= 47236128]

files = listdir(PATH_IN)
codes = []
total_time = 0

for n, line in enumerate(files):
    print('Processing file', line)
    CODE = line[6:-5]
    if line[:6] == 'target' and line[-5:] == '.hdf5':
        print('Code:', CODE)

        start_time = time.time()
        means_vars(CODE, PATH_IN, PATH_OUT)
        end_time = time.time()
        print('Time Required: %.2f' % (end_time-start_time),'sec')
	#total_time += (end_time - start_time)
    else:
        print('Not able to process this file!')

print(n, 'files processed')
print('Average Time Required: %.2f' % total_time/n)
print('Start merging the files')

# creates two files containing all data retrieved so far

PATH_IN = PATH_OUT
PATH_OUT = ''

files = listdir(PATH_IN)
n_files = len(files)

means_array = np.empty((n_files, n_frame, 3))
vars_array = np.empty((n_files, n_frame, 2))

for ind in range(n_files):
    with open(PATH_IN+files[ind], 'rb') as infile:
        means_true, vars_true = pickle.load(infile)

        means_array[ind,:,:] = means_true
        vars_array[ind,:,:] = vars_true

with open(PATH_OUT+'means_array.p', 'wb') as outfile:
        pickle.dump(means_array, outfile)

with open(PATH_OUT+'vars_array.p', 'wb') as outfile:
        pickle.dump(vars_array, outfile)

print('THE END!')


import tkinter as tk
import time
from MXMqtt import MXMqtt
import mcpi.minecraft as minecraft
import mcpi.block as block
import threading

global state
state=0
mc=minecraft.Minecraft.create('47.100.46.95',4784)
entityId= mc.getPlayerEntityId("W")

MQTTHOST="mqtt.16302.com"
MQTTPORT=1883
mqtt=MXMqtt(MQTTHOST,MQTTPORT)

topic="chat"
mqtt.SUB(topic)

def detectpos(x,y,z):
    pos=mc.entity.getTilePos(entityId)
    if pos.x==x and pos.y==y and pos.z==z:
        for i in range(5):
            mc.postToChat(str(i+1))
            time.sleep(1)
        pos=mc.entity.getTilePos(entityId)
        if pos.x==x and pos.y==y and pos.z==z:
            return 1
    else:
        return 0

def stop():
    #mc.postToChat("stop")
    print("stop")
    mqtt.PUB(topic,"4")
def go():
    mc.postToChat("go")
    print("go")
    mqtt.PUB(topic,"0")
def back():
    mc.postToChat("back")
    print("back")
    mqtt.PUB(topic,"3")
def left():
    mc.postToChat("left")
    print("left")
    mqtt.PUB(topic,"1")
def right():
    mc.postToChat("right")
    print("right")
    mqtt.PUB(topic,"2")

def mccardetect():
    global state
    while True:
        if detectpos(1252,4,1147)==1:
            state=1
            time.sleep(120)
        else:
            state=0

def start():
    global state
    while True:
        if state:
            pos2=mc.entity.getTilePos(entityId)
            time.sleep(1)
            pos1=mc.entity.getTilePos(entityId)
            if pos2.x-pos1.x>3:
                right()
            elif pos2.x-pos1.x<-3:
                left()
            elif pos2.z-pos1.z>3:
                back()
            elif pos2.z-pos1.z<-3:
                go()
            else:
                stop()

def main():
    thread_1=threading.Thread(target=mccardetect)
    thread_1.start()
    thread_2=threading.Thread(target=start)
    thread_2.start()
if __name__=='__main__':
    main()


import matplotlib.pyplot as pyplot

x = []
y = []

for i in range(-10000, 10000):
    x.append(i/100)
    y.append(i/100)

pyplot.plot(x, y)
pyplot.xscale('linear')
pyplot.yscale('linear')
pyplot.show()

pyplot.plot(x, y)
pyplot.xscale('log')
pyplot.show()


import gym
import numpy as np

from garage.envs import normalize
from garage.tf.policies import CategoricalMLPPolicy
from garage.tf.envs import TfEnv

env = TfEnv(env_name='MountainCar-v0')
env.reset()
policy = CategoricalMLPPolicy(env.spec, hidden_sizes=(8,))

N = 100
T = 1000
n_itr = 100
discount = 0.9
learning_rate = 0.01

# Set up tensorflow stuff to perform policy updates
observations_var = env.observation_space.new_tensor_variable(
        name='observations', extra_dims=1)
actions_var = env.action_space.new_tensor_variable(
        name='actions', extra_dims=1)
returns_var = tf.placeholder(name='returns')

dist_info_vars = policy.dist_info_sym(observations_var, actions_var)
dist = policy.distribution
surr = -tf.reduce_mean(dist.log_likelihood_sym(
    actions_var, dist_info_vars) * returns_var)
params = policy.get_params(trainable=True)
grads = tf.gradient(surr, params)

f_train = tensor_utils.compile_function(
        inputs=[observations_var, actions_var, returns_var],
        outputs=adam(grads, params, learning_rate=learning_rate))

for i in range(n_itr):
    paths = []

    for _ in range(N):
        observations = []
        actions = []
        rewards = []

        observation = env.reset()

        for _ in range(T):
            action, _ = policy.get_action(observation)
            next_observation, reward, terminal, _ = env.step(action)
            observations.append(observation)
            actions.append(action)
            rewards.append(reward)
            observation = next_observation
            if terminal:
                break

        returns = []
        return_so_far = 0
        for t in range(len(rewards) - 1, -1, -1):
            return_so_far = rewards[t] + discount * return_so_far
            returns.append(return_so_far)
        returns = returns[::-1]

        paths.append(dict(
            observations=np.array(observations),
            actions=np.array(actions),
            rewards=np.array(rewards),
            returns=np.array(returns)
        ))

    observations = np.concatenate([p['observations'] for p in paths])
    actions = np.concatenate([p['actions'] for p in paths])
    returns = np.concatenate([p['returns'] for p in paths])

#    observations_var = env.observation_space.new_tensor_variable(
#            name='observations', extra_dims=1)
#    actions_var = env.action_space.new_tensor_variable(
#            name='actions', extra_dims=1)
#    returns_var = tf.placeholder(name='returns')
#
#    dist_info_vars = policy.dist_info_sym(observations_var, actions_var)
#    dist = policy.distribution
#    surr = -tf.reduce_mean(dist.log_likelihood_sym(
#        actions_var, dist_info_vars) * returns_var)
#    params = policy.get_params(trainable=True)
#    grads = tf.gradient(surr, params)
#
#    f_train = tensor_utils.compile_function(
#            inputs=[observations_var, actions_var, returns_var],
#            outputs=adam(grads, params, learning_rate=learning_rate))
    f_train(observations, actions, returns)

    print('Average return: ', np.mean([sum(path['rewards']) \
            for path in paths]))


# Premier Projet d'Informatique

import pygame, math, random

# CONSTANTES

BLANC = (255, 255, 255)
NOIR = (0, 0, 0)
GRIS = (96, 96, 96)
ROUGE = (255, 0, 0)
VERT = (0, 255, 0)
VERT_FONCE = (0, 155, 0)
BLEU = (0, 0, 255)
JAUNE = (255, 255, 0)
BLEU_CIEL = (119, 181, 254)
HERBE = (34, 120, 15)
MAUVE = (153, 0, 153)

DROITE = pygame.K_RIGHT
GAUCHE = pygame.K_LEFT
HAUT = pygame.K_UP
BAS = pygame.K_DOWN
D = pygame.K_d
Q = pygame.K_q
Z = pygame.K_z
S = pygame.K_s
MENU_DROITE = pygame.K_RIGHT
MENU_GAUCHE = pygame.K_LEFT
MENU_HAUT = pygame.K_UP
MENU_BAS = pygame.K_DOWN
ENTREE = pygame.K_RETURN
P = pygame.K_p
ESPACE = pygame.K_SPACE

PI = math.pi

# PARAMETRES

# Fenetre
FENETRE_LARGEUR = 1280
FENETRE_HAUTEUR = 720
IMAGES_PAR_SECONDE = 60

# Jeu
VIE_MAX = 10
TAILLE = 15
MANIABILITE = 25
VITESSE_MAX = 8
VITESSE_MIN = VITESSE_MAX//2
PUISSANCE = 20
RESISTANCE = 20
DELAI_TIR = 15
BALLE_VITESSE = 15
BALLE_LONGUEUR = 20
BALLE_EPAISSEUR = 3
MANCHE_MIN = 3
COLLISION = False
POWER = True
GRAVITE = 6

# FONCTIONS

def gerer_entree():
    for evenement in pygame.event.get():
        if evenement.type == pygame.QUIT:
            global Fini, Jeu
            Fini = True

        if(Jeu == False and evenement.type == pygame.KEYDOWN and evenement.key == ENTREE):
            Jeu = True

        else:
            if evenement.type == pygame.KEYDOWN:
                if evenement.key == P or evenement.key == ESPACE:
                    global Pause, Pause_delai
                    Pause_delai = 100
                    if Pause:
                        Pause = False
                    else:
                        Pause = True
            if Pause:
                if evenement.type == pygame.KEYDOWN:
                    global select
                    if evenement.key == HAUT or evenement.key == Z:
                        select[0] -= 1
                    elif evenement.key == BAS or evenement.key == S:
                        select[0] += 1
                    elif evenement.key == ENTREE:
                        if select[0] == 0:
                            Pause = False
                        if select[0] == 1:
                            Pause = False
                            reinitialiser(True)
                            for avion in avions:
                                avion['score'] = 0
                                avion['ajoute_vitesse'] = 0
                                avion['ajoute_inclinaison'] = 0
                        if select[0] == 2:
                            Pause = False
                            reinitialiser(True)
                            Jeu = False

            else:
                if evenement.type == pygame.KEYDOWN:

                    if evenement.key == DROITE:
                        avions[0]['ajoute_inclinaison'] += PI * (MANIABILITE/1000)
                    if evenement.key == GAUCHE:
                        avions[0]['ajoute_inclinaison'] -= PI * (MANIABILITE/1000)
                    if evenement.key == HAUT:
                        avions[0]['ajoute_vitesse'] += PUISSANCE/1000
                    if evenement.key == BAS:
                        avions[0]['ajoute_vitesse'] -= PUISSANCE/1000

                    if evenement.key == D:
                        avions[1]['ajoute_inclinaison'] += PI * (MANIABILITE/1000)
                    if evenement.key == Q:
                        avions[1]['ajoute_inclinaison'] -= PI * (MANIABILITE/1000)
                    if evenement.key == Z:
                        avions[1]['ajoute_vitesse'] += PUISSANCE/1000
                    if evenement.key == S:
                        avions[1]['ajoute_vitesse'] -= PUISSANCE/1000

                if evenement.type == pygame.KEYUP:

                    if evenement.key == DROITE:
                        avions[0]['ajoute_inclinaison'] -= PI * (MANIABILITE/1000)
                    if evenement.key == GAUCHE:
                        avions[0]['ajoute_inclinaison'] += PI * (MANIABILITE/1000)
                    if evenement.key == HAUT:
                        avions[0]['ajoute_vitesse'] -= PUISSANCE/1000
                    if evenement.key == BAS:
                        avions[0]['ajoute_vitesse'] += PUISSANCE/1000

                    if evenement.key == D:
                        avions[1]['ajoute_inclinaison'] -= PI * (MANIABILITE/1000)
                    if evenement.key == Q:
                        avions[1]['ajoute_inclinaison'] += PI * (MANIABILITE/1000)
                    if evenement.key == Z:
                        avions[1]['ajoute_vitesse'] -= PUISSANCE/1000
                    if evenement.key == S:
                        avions[1]['ajoute_vitesse'] += PUISSANCE/1000

def gerer_entree_menu():
    for evenement in pygame.event.get():
        global select, Fini, Jeu, Option
        if evenement.type == pygame.QUIT:
            Fini = True
        elif evenement.type == pygame.KEYDOWN:
            if evenement.key == pygame.K_BACKSPACE:
                if (select[1]+select[0]*12) < len(options) and options[select[1]] < 100 :
                    if select[1]+select[0]*12 == 10:
                        options[10] = False
                    elif select[1]+select[0]*12 == 11:
                        options[11] = False
                    else:
                        options[select[1]+select[0]*12] -= 1
            elif evenement.key == ENTREE:
                if(Option):
                    if select[1] == 12:
                        Option = False
                        mettre_a_jour_options()
                        reinitialiser(True)
                    elif (select[1]+select[0]*12) < len(options) and options[select[1]] < 100:
                        if select[1]+select[0]*12 == 10:
                            options[10] = True
                        elif select[1]+select[0]*12 == 11:
                            options[11] = True
                        else:
                            options[select[1]+select[0]*12] += 1

                elif select[1] == 0:
                    global manche
                    Jeu = True
                    for avion in avions:
                        avion['score'] = 0
                        avion['ajoute_vitesse'] = 0
                        avion['ajoute_inclinaison'] = 0
                        manche = 0
                elif select[1] == 1:
                    Option = True
                    select = [0, 0]
                elif select[1] == 2:
                    Fini = True

            if evenement.key == MENU_BAS:
                select[1] += 1
            elif evenement.key == MENU_HAUT:
                select[1] -= 1
            elif evenement.key == MENU_GAUCHE:
                select[0] -= 1
            elif evenement.key == MENU_DROITE:
                select[0] += 1

def menu_pause():
    global Pause, Pause_delai
    if Pause:
        select[0] %= 3
        largeur = 400
        hauteur = 600
        pygame.draw.rect(fenetre, BLANC, (5, 5, 10, 25))
        pygame.draw.rect(fenetre, BLANC, (20, 5, 10, 25))
        pygame.draw.rect(fenetre, GRIS, (dimensions_fenetre[0]/2 - largeur/2, dimensions_fenetre[1]/2 - hauteur/2, largeur, hauteur))
        police  = pygame.font.Font("police/crochet.otf", 100)
        affiche_message("PAUSE", police, (dimensions_fenetre[0]/2, dimensions_fenetre[1]/2 - 4*hauteur/4 + 380), BLANC)
        police  = pygame.font.Font("police/crochet.otf", 60)

        couleurs = [BLANC, BLANC, BLANC]
        i = 0
        for i in range(3):
            if select[0] == i:
                couleurs[i] = JAUNE
            else:
                couleurs[i] = BLANC

        affiche_message("Continuer", police, (dimensions_fenetre[0]/2, dimensions_fenetre[1]/2 - 3*hauteur/4 + 380), couleurs[0])
        affiche_message("Recommencer", police, (dimensions_fenetre[0]/2, dimensions_fenetre[1]/2 - 2*hauteur/4 + 380), couleurs[1])
        affiche_message("Quitter", police, (dimensions_fenetre[0]/2, dimensions_fenetre[1]/2 - 1*hauteur/4 + 380), couleurs[2])
    elif Pause_delai > 0:
        Pause_delai -= 1
        pygame.draw.polygon (fenetre, BLANC, [(5, 5), (5,30), (30, 17.5)])

def affiche_menu():
    global select, Option
    fenetre.fill(BLEU_CIEL)
    temps = pygame.time.get_ticks()
    if Option:
        select[1] %= 13
        select[0] %= len(options)//12 + 1

        if select[1] == 12:
            dessiner_fleche((FENETRE_LARGEUR//2 - 160, 19*FENETRE_HAUTEUR//20) ,NOIR, 80, 16, 16, 2)
            dessiner_fleche((FENETRE_LARGEUR//2 - 160, 19*FENETRE_HAUTEUR//20) ,VERT, 80, 16, 16)

        else:
            dessiner_fleche((430 + select[0]*FENETRE_LARGEUR//3,  6*FENETRE_HAUTEUR//20 + select[1]*(1*FENETRE_HAUTEUR//20)),NOIR, 80, 16, 16, 2)
            dessiner_fleche((430 + select[0]*FENETRE_LARGEUR//3,   6*FENETRE_HAUTEUR//20 + select[1]*(1*FENETRE_HAUTEUR//20)),VERT, 80, 16, 16)

        police  = pygame.font.Font("police/crochet.otf", 100)
        affiche_message_centre("Options", police, (FENETRE_LARGEUR//2, FENETRE_HAUTEUR//8), 26, 10, NOIR, BLEU)
        police  = pygame.font.Font("police/crochet.otf", 24)

        for i in range(0, len(options)):
            if i > 11:
                j = i%11
                affiche_message(options_noms[i].format(options[i]), police, (FENETRE_LARGEUR//2 + (i//12)*FENETRE_LARGEUR//3, (j+5)*FENETRE_HAUTEUR//20), NOIR)
            else:
                affiche_message(options_noms[i].format(options[i]), police, (FENETRE_LARGEUR//2, (i+6)*FENETRE_HAUTEUR//20), NOIR)

        police  = pygame.font.Font("police/crochet.otf", 36)
        affiche_message_centre("Quitter", police, (FENETRE_LARGEUR//2, 19*FENETRE_HAUTEUR//20), 16, 4, NOIR, ROUGE)

    else:
        delai = 1000
        select[1] %= 3
        police  = pygame.font.Font("police/crochet.otf", 200)
        if( temps%delai <  delai/2 ):
            affiche_message_centre(" AIRPLANES ", police, (FENETRE_LARGEUR//2, FENETRE_HAUTEUR//5), 26, 10, ROUGE, MAUVE)
        else:
            affiche_message_centre(" AIRPLANES ", police, (FENETRE_LARGEUR//2, FENETRE_HAUTEUR//5), 26, 10, VERT, MAUVE)

        dessiner_fleche((50 + 6*FENETRE_LARGEUR//20, 11*FENETRE_HAUTEUR//20 + select[1]*(3*FENETRE_HAUTEUR//20)),NOIR, 80, 16, 16, 2)
        dessiner_fleche((50 + 6*FENETRE_LARGEUR//20, 11*FENETRE_HAUTEUR//20 + select[1]*(3*FENETRE_HAUTEUR//20)),VERT, 80, 16, 16)

        police  = pygame.font.Font("police/crochet.otf", 64)
        affiche_message_centre(" Jouer ", police, (FENETRE_LARGEUR//2, 11*FENETRE_HAUTEUR//20), 16, 4, NOIR, VERT_FONCE)
        affiche_message_centre(" Options ", police, (FENETRE_LARGEUR//2, 14*FENETRE_HAUTEUR//20), 16, 4, NOIR, BLEU)
        affiche_message_centre(" Quitter ", police, (FENETRE_LARGEUR//2, 17*FENETRE_HAUTEUR//20), 16, 4, NOIR, ROUGE)

    pygame.display.flip()
    horloge.tick(10)

def mettre_a_jour_options():
    global VIE_MAX, VITESSE_MAX, PUISSANCE, MANIABILITE, RESISTANCE, TAILLE, BALLE_VITESSE, BALLE_LONGUEUR, BALLE_EPAISSEUR, DELAI_TIR, VITESSE_MIN, MANCHE_MIN, COLLISION, POWER
    VIE_MAX = options[0]
    VITESSE_MAX = options[1]
    VITESSE_MIN = VITESSE_MAX/2
    PUISSANCE = options[2]
    MANIABILITE = options[3]
    RESISTANCE = options[4]
    BALLE_VITESSE = options[5]
    BALLE_LONGUEUR = options[6]
    BALLE_EPAISSEUR = options[7]
    DELAI_TIR = options[8]
    MANCHE_MIN = options[9]
    COLLISION = options[10]
    POWER = options[11]

def affiche_message_centre(texte, police, position, marge, epaisseur, couleur1 = NOIR, couleur2 = BLANC, gras = True, contour = True):
    message = police.render(texte, gras, couleur1)
    message_largeur, message_hauteur = police.size(texte)
    if contour:
        pygame.draw.rect(fenetre, couleur1, (position[0] - message_largeur//2 - marge//2, position[1] - message_hauteur//2 - marge//2, message_largeur + marge, message_hauteur + marge))
        marge -= epaisseur
    pygame.draw.rect(fenetre, couleur2, (position[0] - message_largeur//2 - marge//2, position[1] - message_hauteur//2 - marge//2, message_largeur + marge, message_hauteur + marge))
    fenetre.blit(message, (position[0] - message_largeur//2, position[1] - message_hauteur//2))

def affiche_message(texte, police, position, couleur1, gras=True):
    message = police.render(texte, gras, couleur1)
    message_largeur, message_hauteur = police.size(texte)
    fenetre.blit(message, (position[0] - message_largeur/2, position[1]- message_hauteur/2))

def dessiner_fleche(position, couleur, L, l, c, contour=0):
    dessine_triangle((position[0]+L//2, position[1]), couleur, c, contour)
    pygame.draw.rect(fenetre, couleur, (position[0] - L//2 - contour, position[1] - l//2 - contour, L+2*contour, l+2*contour))

def dessine_triangle(position, couleur, c, contour):
    pt1 = (position[0] - contour, position[1] + c + 2*contour)
    pt2 = (position[0] + 2*c + 2*contour, position[1])
    pt3 = (position[0] - contour, position[1] - c - 2*contour)
    pygame.draw.polygon(fenetre, couleur ,(pt1,pt2,pt3))

def maj_positions():
    global temps
    i = 0
    k = 0
    for avion in avions:
        if avion['vie'] <= 0:
            global t, ori, first
            if first[i]:
                crash.play()
                ori[i] = avion['orientation']
                first[i] = False
            t[i] += 1
            avion['tir_delai'] = 1000

            avion['position'][1] += avion['vitesse']*math.sin(ori[i])+GRAVITE*t[i]*t[i]/1000
            avion['position'][0] += avion['vitesse']*math.cos(ori[i])
            if(math.sin(avion['orientation']) < 0.95):

                if (math.cos(ori[i]) >= 0):
                    avion['orientation'] += PI/120
                else:
                    avion['orientation'] -= PI/120

        else:
            avion['vitesse'] += avion['ajoute_vitesse'] / ((VIE_MAX + RESISTANCE) / (avion['vie'] + RESISTANCE))
            avion['orientation'] += avion['ajoute_inclinaison'] / ((VIE_MAX +RESISTANCE) / (avion['vie'] + RESISTANCE))
            if(avion['vitesse'] > VITESSE_MAX):
                avion['vitesse'] = VITESSE_MAX
            elif(avion['vitesse'] < VITESSE_MIN):
                avion['vitesse'] = VITESSE_MIN
            if(avion['vitesse'] < (VITESSE_MIN + VITESSE_MAX)/2):
                avion['position'][1] += ((VITESSE_MIN + VITESSE_MAX)/2 - avion['vitesse'])*GRAVITE
            avion['position'][0] += avion['vitesse']*math.cos(avion['orientation'])
            avion['position'][1] += avion['vitesse']*math.sin(avion['orientation'])

            if sorti_haut(avion['position'], dimensions_avion[1]):
                avion['vitesse'] -= 0.1
            if sorti_gauche(avion['position'], dimensions_avion[0]):
                avion['position'][0] = FENETRE_LARGEUR + dimensions_avion[0]
            if sorti_droite(avion['position'], dimensions_avion[0]):
                avion['position'][0] = -dimensions_avion[0]
        i += 1

        if(avion['position'][1] > (dimensions_fenetre[1] - hauteur_sol(avion['position'][0], temps_maintenant))):
            avion['vie'] = 0
            avions[(k+1)%2]['score'] += 1
            crash.stop()
            boom.play()
            ajoute_explosion(avion['position'], 1)
            affiche_explosion()
            pygame.display.flip()
            pygame.time.wait(1000)
            reinitialiser()
        k += 1

def maj_balles():
    i = 0
    for avion in avions:
        if(avion['tir_delai'] > 0):
            avion['tir_delai'] -= 1
        if(avion['tir_delai'] == 0):
            avion['balles'] += [((avion['position'][0], avion['position'][1]), avion['orientation'])]
            avion['tir_delai'] = DELAI_TIR
            tir.play()
        j = 0
        for balle in avion['balles']:
            avions[i]['balles'][j] = ((balle[0][0] + BALLE_VITESSE*math.cos(balle[1]), (balle[0][1] + BALLE_VITESSE*math.sin(balle[1]))), balle[1])
            if sorti_fenetre(balle[0], dimensions_avion[0]//2):
                del(avions[i]['balles'][j])
            j += 1
        i += 1

def affiche_avions():
    for avion in avions:
        avion['rectangle'], image = rotation_centre(avion['image'], avion['rectangle'], avion['orientation'] + PI/20)
        position = (avion['position'][0] - avion['rectangle'][0]/2, avion['position'][1] - avion['rectangle'][1]/2)
        fenetre.blit(image, (int(position[0]), int(position[1])))

def affiche_balles():
    for avion in avions:
        for balle in avion['balles']:
            l = 1
            while(l < BALLE_LONGUEUR):
                pygame.draw.circle(fenetre, GRIS, (int(balle[0][0] - l*math.cos(balle[1])), int(balle[0][1] - l*math.sin(balle[1]))), BALLE_EPAISSEUR)
                l += 1
            pygame.draw.circle(fenetre, JAUNE, (int(balle[0][0]), int(balle[0][1])), BALLE_EPAISSEUR)
            pygame.draw.circle(fenetre, JAUNE, (int(balle[0][0]), int(balle[0][1])), BALLE_EPAISSEUR)

def affiche_nuage():
    i = 0
    for nuage in nuages:
        nuages[i] = (nuage[0]-1, nuage[1])
        fenetre.blit(IMAGE_NUAGE, (int(nuage[0]), int(nuage[1])))
        if sorti_horizontal(nuage, dimensions_nuage[0]):
            nuages[i] = (dimensions_fenetre[0] + dimensions_nuage[0], nuage[1])
        i += 1

def affiche_vies():
    for avion in avions:
        if(avion['vie'] < 0):
            avion['vie'] = 0
        if(avion['vie_delai'] >= 0):
            pygame.draw.rect(fenetre, NOIR, (avion['position'][0] - 26, avion['position'][1] - 1 - dimensions_avion[0]//1.5, 52, 10))
            pygame.draw.rect(fenetre, ROUGE, (avion['position'][0] - 25, avion['position'][1] - dimensions_avion[0]//1.5, 50, 8))
            pygame.draw.rect(fenetre, VERT, (avion['position'][0] - 25, avion['position'][1] - dimensions_avion[0]//1.5, 50*avion['vie']//VIE_MAX, 8))
            avion['vie_delai'] -= 1

def dessiner_sol1(temps):
    for x in range(dimensions_fenetre[0]):

        y = hauteur_sol(x, temps)
        pygame.draw.line(fenetre, VERT_FONCE, (x, dimensions_fenetre[1] - y), (x, dimensions_fenetre[1]))

def dessiner_sol2(temps):
    for x in range(dimensions_fenetre[0]):
        y = hauteur_sol(x, temps, 120, 100, 30)
        pygame.draw.line(fenetre, HERBE, (x, dimensions_fenetre[1] - y), (x, dimensions_fenetre[1]))

def score():
    global manche, MANCHE_MIN
    police = pygame.font.Font("police/crochet.otf", 42)
    if (manche+1) >= MANCHE_MIN:
        affiche_message("Manche finale", police, (FENETRE_LARGEUR//2, 22), NOIR)
    else:
        affiche_message("Manche {:d}".format(manche+1), police, (FENETRE_LARGEUR//2, 22), NOIR)
    affiche_message(":".format(avions[0]['score'], ), police, (FENETRE_LARGEUR//2, 58), NOIR)
    affiche_message("{:d}".format(avions[0]['score'], ), police, (FENETRE_LARGEUR//2 + 30, 60), ROUGE)
    affiche_message("{:d}".format(avions[1]['score'], ), police, (FENETRE_LARGEUR//2 - 30, 60), VERT)

def collision():
    global COLLISION
    for avion1 in avions:
        j = 0
        for power in power_up_list:
            d3 = distance2(power, avion1['position'])
            if(avion1['vie'] > 0 and d3 < ((dimensions_avion[1]/1.5)**2)):
                global DELAI_POWER_UP
                DELAI_POWER_UP = random.randint(200, 1000)
                del power_up_list[j]
                avion1['vie'] += VIE_MAX//4
                if avion1['vie'] > VIE_MAX:
                    avion1['vie'] = VIE_MAX
                avion1['vie_delai'] = 90
            j += 1
        for avion2 in avions:
            if COLLISION:
                d2 = distance2(avion1['position'], avion2['position'])
                if(avion1['image'] != avion2['image'] and avion1['vie'] > 0 and d2 < ((dimensions_avion[1]/1.5)**2)):
                    boom.play()
                    avion1['vie'] = 0
                    avion2['vie'] = 0
                    avion1['vie_delai'] = 90
                    avion2['vie_delai'] = 90
                    inter = ((avion1['position'][0]+avion2['position'][0])//2, (avion1['position'][1]+avion2['position'][1])//2)
                    ajoute_explosion(inter, 30)
            i = 0
            for balle in avion1['balles']:
                d = distance2(balle[0], (avion2['position'][0], avion2['position'][1]))
                if(avion1['image'] != avion2['image'] and d < ((dimensions_avion[1]/1.5)**2)):
                    del(avion1['balles'][i])
                    degat_avion(avion2)
                i += 1

def ajoute_explosion(position, duree):
    global explosions
    explosions += [((position[0] - dimensions_explo[0]//2, position[1] - dimensions_explo[1]//2), duree)]

def affiche_explosion():
    global explosions
    i = 0
    for explosion in explosions:
        if explosion[1] > 0:
            fenetre.blit(IMAGE_EXPLO, (explosion[0][0], explosion[0][1]))
            explosions[i] = (explosion[0], explosion[1] - 1)
        else:
            del(explosions[i])
        i += 1

def degat_avion(avion):
    avion['vie_delai'] = 90
    avion['vie'] -= 1
    avion['tir_delai'] = 60

def nouvel_avion(image):
    return {
    'image' : image,
    'position' : [],
    'vitesse' : VITESSE_MAX,
    'orientation' : 0,
    'rectangle' : image.get_size(),
    'ajoute_vitesse' : 0,
    'ajoute_inclinaison' : 0,
    'balles' : [],
    'tir_delai' : DELAI_TIR,
    'vie' : VIE_MAX,
    'vie_delai' : 0,
    'score' : 0
    }

def sorti_fenetre(point, marge=0):
    if sorti_vertical(point, marge) or sorti_horizontal(point, marge):
        return True
    else:
        return False

def sorti_vertical(point, marge=0):
    if(sorti_bas(point, marge) or sorti_haut(point, marge)):
        return True
    else:
        return False

def sorti_horizontal(point, marge=0):
    if(sorti_gauche(point, marge) or sorti_droite(point, marge)):
        return True
    else:
        return False

def sorti_droite(point, marge=0):
    if(point[0] > FENETRE_LARGEUR + marge):
        return True
    else:
        return False

def sorti_gauche(point, marge=0):
    if(point[0] < -marge):
        return True
    else:
        return False

def sorti_haut(point, marge=0):
    if(point[1] < -marge):
        return True
    else:
        return False

def sorti_bas(point, marge=0):
    if(point[1] > FENETRE_HAUTEUR + marge):
        return True
    else:
        return False

def rotation_centre(image, rectangle, angle):
    image2 = pygame.transform.rotate(image, -angle*180/PI)
    rectangle2 = image2.get_size()
    return rectangle2, image2

def distance2(pt1, pt2):
    dh = pt1[0] - pt2[0]
    dv = pt1[1] - pt2[1]
    d2 = dh*dh + dv*dv
    return d2

def hauteur_sol(x, temps=0, hauteur = 40, etireX = 50, etireY = 20):
    alpha = (-x - temps)/ etireX
    y = etireY * math.exp(math.cos(alpha)) / math.e + hauteur
    return y

def fait_nuage():
    global nuages
    i = 0
    while (i < 14):
        x = random.randint(-dimensions_nuage[0], dimensions_fenetre[0] + dimensions_nuage[0])
        y = random.randint(0, dimensions_fenetre[1]//2)
        nuages += [(x, y)]
        i += 1

def reinitialiser(new=False):
    global init, manche, Fini, t, first, ori, Jeu, power_up_list
    t = [0, 0]
    ori = [0, 0]
    first = [True, True]
    power_up_list = []

    avions[0]['position'] = [3*FENETRE_LARGEUR/4, FENETRE_HAUTEUR/2]
    avions[0]['orientation'] = PI
    avions[1]['position'] = [FENETRE_LARGEUR/4, FENETRE_HAUTEUR/2]
    avions[1]['orientation'] = 0
    for avion in avions:
        avion['vitesse'] = VITESSE_MAX
        avion['vie'] = VIE_MAX
        avion['vie_delai'] = 0
        avion['balles'] = []
        avion['tir_delai'] = 120
        if new:
            avion['score'] = 0

    if new:
        manche = 0
    else:
        manche += 1
        if(manche >= MANCHE_MIN and abs(avions[0]['score'] - avions[1]['score']) > 0):
            Jeu = False
            manche = 0
            police  = pygame.font.Font("police/crochet.otf", 150)
            if avions[0]['score'] > avions[1]['score']:
                affiche_message("Le joueur 1 a gagné !", police, (dimensions_fenetre[0]/2, dimensions_fenetre[1]/3), ROUGE)
            elif avions[1]['score'] > avions[0]['score']:
                affiche_message("Le joueur 2 a gagné !", police, (dimensions_fenetre[0]/2, dimensions_fenetre[1]/3), VERT_FONCE)
            else:
                affiche_message("Egalité !", police, (dimensions_fenetre[0]/2, dimensions_fenetre[1]/3), NOIR)
            pygame.display.flip()
            pygame.time.wait(2000)
    init = True

def power_up():
    global DELAI_POWER_UP, power_up_list
    if DELAI_POWER_UP > 0:
        DELAI_POWER_UP -= 1
    else:
        DELAI_POWER_UP = 1200
        ajoute_power_up()
    i = 0
    for power in power_up_list:
        power_up_list[i] = (power[0], power[1]+1)
    i += 1

def ajoute_power_up():
    global power_up_list
    pos = (random.randint(50, dimensions_fenetre[0]-50), -50)
    power_up_list += [pos]

def affiche_power_up():
    for power in power_up_list:
        fenetre.blit(IMAGE_CLE, (power[0]-dimensions_cle[0]//2, power[1]-dimensions_cle[1]//2))

# INITIALISATION

pygame.mixer.pre_init(44100, -16, 1, 512)
pygame.mixer.init()
pygame.font.init()
pygame.init()

dimensions_fenetre = (FENETRE_LARGEUR, FENETRE_HAUTEUR)
fenetre = pygame.display.set_mode(dimensions_fenetre)
pygame.display.set_caption("Airplanes")

crash = pygame.mixer.Sound("sons/crash.wav")
boom = pygame.mixer.Sound("sons/explosion.wav")
tir = pygame.mixer.Sound("sons/tir.wav")
tir.set_volume(0.1)
pygame.mixer.music.load("sons/RGT.wav")
pygame.mixer.music.set_volume(0.8)
pygame.mixer.music.play(-1)

IMAGE_AVION_VERT_ORIGINE = pygame.image.load('images/aircraft_green.png').convert_alpha(fenetre)
IMAGE_AVION_ROUGE_ORIGINE = pygame.image.load('images/aircraft_red.png').convert_alpha(fenetre)
dimensions_avion = IMAGE_AVION_VERT_ORIGINE.get_size()
rapport = 100/TAILLE
dimensions_avion = (dimensions_avion[0]/rapport, dimensions_avion[1]/rapport)
IMAGE_AVION_VERT = pygame.transform.scale(IMAGE_AVION_VERT_ORIGINE, (int(dimensions_avion[0]), int(dimensions_avion[1])))
IMAGE_AVION_ROUGE = pygame.transform.scale(IMAGE_AVION_ROUGE_ORIGINE, (int(dimensions_avion[0]), int(dimensions_avion[1])))

IMAGE_NUAGE = pygame.image.load('images/cloud.png').convert_alpha(fenetre)
dimensions_nuage = IMAGE_NUAGE.get_size()
dimensions_nuage = (dimensions_nuage[0]*2, dimensions_nuage[1]*2)
IMAGE_NUAGE = pygame.transform.scale(IMAGE_NUAGE, (dimensions_nuage[0], dimensions_nuage[1]))

IMAGE_EXPLO = pygame.image.load('images/explo.png').convert_alpha(fenetre)
dimensions_explo = IMAGE_EXPLO.get_size()
dimensions_explo = (dimensions_explo[0]/(3*rapport), dimensions_explo[1]/(3*rapport))
IMAGE_EXPLO = pygame.transform.scale(IMAGE_EXPLO, (int(dimensions_explo[0]), int(dimensions_explo[1])))

IMAGE_CLE = pygame.image.load('images/cle.png')
dimensions_cle = IMAGE_CLE.get_size()
dimensions_cle = (dimensions_cle[0]/15, dimensions_cle[1]/15)
IMAGE_CLE = pygame.transform.scale(IMAGE_CLE, (int(dimensions_cle[0]), int(dimensions_cle[1])))

explosions = []
nuages = []
avions = []
avions += [nouvel_avion(IMAGE_AVION_ROUGE)]
avions += [nouvel_avion(IMAGE_AVION_VERT)]

options = [VIE_MAX, VITESSE_MAX, PUISSANCE, MANIABILITE, RESISTANCE, BALLE_VITESSE, BALLE_LONGUEUR, BALLE_EPAISSEUR, DELAI_TIR, MANCHE_MIN, COLLISION, POWER]
options_noms = ["Vie              : {:d}", "Vitesse max      : {:d}", "Puissance        : {:d}", "Maniabilite      : {:d}", "Resistance       : {:d}", "Vitesse balles   : {:d}", "Longueur balles  : {:d}", "Epaisseur balles : {:d}", "Delai entre tirs : {:d}", "Manche           : {:d}","Collision        : {}", "Power up        : {}"]

DELAI_POWER_UP = 500
power_up_list = []
Fini = False
Jeu = False
Option = False
Pause = False
Pause_delai = 0

select = [0, 0]

horloge = pygame.time.Clock()

reinitialiser(True)
fait_nuage()

while not Fini:
    if not Jeu:
        affiche_menu()
        gerer_entree_menu()
    else:
        temps_maintenant = pygame.time.get_ticks()
        gerer_entree()
        if not Pause:
            maj_positions()
            maj_balles()
            if POWER:
                power_up()
        fenetre.fill(BLEU_CIEL)
        dessiner_sol2(temps_maintenant/20)
        affiche_nuage()
        affiche_vies()
        affiche_balles()
        affiche_avions()
        affiche_power_up()
        dessiner_sol1(temps_maintenant/10)
        collision()
        affiche_explosion()
        menu_pause()
        score()
        horloge.tick(IMAGES_PAR_SECONDE)
        pygame.display.flip()
        if init and Jeu:
            init = False
            pygame.time.wait(1000)

pygame.display.quit()
pygame.quit()
exit()


# Author: Sachin Kumar
# Github: https://github.com/skumar24

# Alphabet Rangoli
# Problem Url: https://www.hackerrank.com/challenges/alphabet-rangoli/problem
# Score: 20

def print_rangoli(size):
    alphabets = "abcdefghijklmnopqrstuvwxyz"
    lines = []
    for i in range(size-1, 0, -1):
        line = ""
        for j in range(size-1, -1 + i, -1):
            line += alphabets[j]
            if j != size:
                line += "-"
        for j in range(1 + i, size):
            line += alphabets[j]
            if j != size-1:
                line += "-"
        lines.append(line)
    for i in range(size):
        line = ""
        for j in range(size-1, -1 + i, -1):
            line += alphabets[j]
            if j != size and size > 1:
                line += "-"
        for j in range(1 + i, size):
            line += alphabets[j]
            if j != size-1:
                line += "-"
        lines.append(line)
    for l in lines:
        print(l.center(size * 2 - 1 + ((size - 1) * 2), "-"))


from bpy.types import (
        PropertyGroup,
        )

from bpy.props import (
        StringProperty,
        BoolProperty,
        IntProperty,
        IntVectorProperty,
        FloatProperty,
        FloatVectorProperty,
        EnumProperty,
        PointerProperty,
        CollectionProperty,
        )

from . import enums

class PearRayMaterialProperties(PropertyGroup):
    bsdf = EnumProperty(
        name="BSDF",
        description="BSDF type",
        items=enums.enum_material_bsdf,
        default='COOK_TORRANCE'
    )

    cast_shadows = BoolProperty(
        name="Cast Shadows",
        description="Cast Shadows",
        default=True
    )

    cast_self_shadows = BoolProperty(
        name="Cast Self Shadows",
        description="Cast shadows on himself",
        default=True
    )

    is_camera_visible = BoolProperty(
        name="Camera Visible",
        description="Is visible through the camera",
        default=True
    )

    is_shadeable = BoolProperty(
        name="Shadeable",
        description="Will be shaded",
        default=True
    )

    # Emission
    emission_color_type = EnumProperty(
        name="Emission Color Type",
        description="Emission Color Type",
        items=enums.enum_color_type,
        default='COLOR'
    )
    emission_color = FloatVectorProperty(
        name="Emission Color",
        description="Emission Color",
        default=(0,0,0),
        subtype="COLOR",
        soft_max=1,
    )
    emission_color_temp = FloatProperty(
        name="Emission Color Temperature",
        description="Emission Blackbody Color Temperature",
        min=0, soft_max=100000.00, default=5500, step=100
    )
    emission_color_temp_type = EnumProperty(
        name="Emission Color Temperature Type",
        description="Emission Blackbody Color Temperature Type",
        items=enums.enum_temp_type,
        default='LUM'
    )
    emission_color_temp_factor = FloatProperty(
        name="Emission Color Temperature Normalization Factor",
        description="Emission Blackbody Color Temperature Normalization Factor",
        min=0, soft_max=100000.00, default=1, step=100
    )
    emission_color_tex_slot = IntProperty(
        name="Texture Slot",
        description="Used Texture Slot",
        min=0, soft_max=100000, default=0
    )

    # Diffuse
    diffuse_color_type = EnumProperty(
        name="Diffuse Color Type",
        description="Diffuse Color Type",
        items=enums.enum_color_type,
        default='COLOR'
    )
    diffuse_color_temp = FloatProperty(
        name="Diffuse Color Temperature",
        description="Diffuse Blackbody Color Temperature",
        min=0, soft_max=100000.00, default=1000, step=100
    )
    diffuse_color_temp_type = EnumProperty(
        name="Diffuse Color Temperature Type",
        description="Diffuse Blackbody Color Temperature Type",
        items=enums.enum_temp_type,
        default='LUM'
    )
    diffuse_color_temp_factor = FloatProperty(
        name="Diffuse Color Temperature Normalization Factor",
        description="Diffuse Blackbody Color Temperature Normalization Factor",
        min=0, soft_max=100000.00, default=1, step=100
    )
    diffuse_color_tex_slot = IntProperty(
        name="Texture Slot",
        description="Used Texture Slot",
        min=0, soft_max=100000, default=0
    )

    # Specular
    specular_color_type = EnumProperty(
        name="Specular Color Type",
        description="Specular Color Type",
        items=enums.enum_color_type,
        default='COLOR'
    )
    specular_color_temp = FloatProperty(
        name="Specular Color Temperature",
        description="Specular Blackbody Color Temperature",
        min=0, soft_max=100000.00, default=1000, step=100
    )
    specular_color_temp_type = EnumProperty(
        name="Specular Color Temperature Type",
        description="Specular Blackbody Color Temperature Type",
        items=enums.enum_temp_type,
        default='LUM'
    )
    specular_color_temp_factor = FloatProperty(
        name="Specular Color Temperature Normalization Factor",
        description="Specular Blackbody Color Temperature Normalization Factor",
        min=0, soft_max=100000.00, default=1, step=100
    )
    specular_color_tex_slot = IntProperty(
        name="Texture Slot",
        description="Used Texture Slot",
        min=0, soft_max=100000, default=0
    )
    specular_ior_color = FloatVectorProperty(
        name="Specular Index of Refraction",
        description="Specular Index of Refraction",
        default=(1.55,1.55,1.55),
        subtype="COLOR",
        soft_min=1,
        soft_max=3,
    )
    specular_ior_value = FloatProperty(
        name="Specular Index of Refraction",
        description="Specular Index of Refraction",
        default=1.55,
        soft_min=1,
        soft_max=3,
    )
    specular_ior_type = EnumProperty(
        name="Specular Index of Refraction Type",
        description="Specular Index of Refraction Type",
        items=enums.enum_ior_type,
        default='VALUE'
    )

    # Ward
    spec_roughness_x = FloatProperty(
        name="Roughness X",
        description="Roughness to tangent direction",
        min=0, soft_max=1.00, default=0.50
    )
    spec_roughness_y = FloatProperty(
        name="Roughness Y",
        description="Roughness to binormal direction",
        min=0, soft_max=1.00, default=0.50
    )
    reflectivity = FloatProperty(
        name="Reflectivity",
        description="Reflectivity of material",
        min=0, soft_max=1.00, default=0.50
    )

    # CookTorrance
    ct_fresnel_mode = EnumProperty(
        name="Fresnel Mode",
        description="Fresnel Mode",
        items=enums.enum_material_ct_fresnel_mode,
        default='DIELECTRIC'
    )

    ct_distribution_mode = EnumProperty(
        name="Distribution Mode",
        description="Distribution Mode",
        items=enums.enum_material_ct_distribution_mode,
        default='GGX'
    )

    ct_geometry_mode = EnumProperty(
        name="Geometry Mode",
        description="Geometry Mode",
        items=enums.enum_material_ct_geometry_mode,
        default='COOK_TORRANCE'
    )

    # Grid
    grid_first_material = None
    grid_second_material = None
    grid_count = IntProperty(
        name="Grid Count",
        description="Grid Count",
        min=1, soft_max=100000, default=10
    )
    grid_tile_uv = BoolProperty(
        name="Tile UV",
        description="Tile the UV coordinates",
        default=True
    )

    # Glass
    glass_is_thin = BoolProperty(
        name="Thin",
        description="Disables total reflections",
        default=False
    )


# %load q03_plot_innings_runs_histogram/build.py
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.switch_backend('agg')
ipl_df = pd.read_csv('data/ipl_dataset.csv', index_col=None)

# Solution
#def plot_innings_runs_histogram():
df1=ipl_df.loc[ipl_df['inning']==1].groupby(['match_code']).agg(sum)['total']
df2=ipl_df.loc[ipl_df['inning']==2].groupby(['match_code']).agg(sum)['total']

fig, axes = plt.subplots(1, 2)

df1.hist('match_code', bins=100, ax=axes[0])
df2.hist('match_code', bins=100, ax=axes[1])

plt.show