{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\nimport warnings\nimport matplotlib.pyplot as plt\nimport math\nimport colorama\nfrom colorama import Fore\nwith warnings.catch_warnings():\n    warnings.simplefilter(action='ignore', category=FutureWarning)\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\ndata=pd.read_csv('/kaggle/input/big-data-derby-2022/nyra_2019_complete.csv',header=None)\ndata[3]=data[3].astype(str).str.strip().replace('1X','1')\ndata[3]=data[3].astype(str).str.strip().replace('3X','3')\ndata[3]=data[3].astype(str).str.strip().replace('2B','2')\ndata[3]=data[3].astype(str).str.strip().replace('1A','1')\ndata[9]=data[9].astype(str).str.strip()\ndata[8]=data[8].astype(str).str.strip()\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-12-03T01:10:25.136813Z","iopub.execute_input":"2022-12-03T01:10:25.137502Z","iopub.status.idle":"2022-12-03T01:10:56.743441Z","shell.execute_reply.started":"2022-12-03T01:10:25.137395Z","shell.execute_reply":"2022-12-03T01:10:56.742540Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **The following works have been done in this notebook:**\n\n* > #### - **Classifying** the track of each horse raceing based on the given **latitude** and **longitude** \n* > ####  Analysing the **geometry** of the track's shape in the **Cartesian Coordinates**. And providing a mathematical method to determine the **position** of jockeys with respect of each other during the race.\n* > ####  **Dividing** the track to different parts based on the **shape** of the track\n* > ####  Developing an **intelligence algorithm** to analyse the **performance** of each jocky in each horse racing and determine if the **end position** of the jockey is a **expected finish position** or not.","metadata":{}},{"cell_type":"code","source":"# some code for preparing data to analyse\nimport colorama\nfrom colorama import Fore\ndef mymax(x):\n     return max([y[5] for y in x])\ndef mymin(x):\n     return min([y[5] for y in x])\ndef imax(x):\n    return np.argmax([y[5] for y in x])\ndef imin(x):\n    return np.argmin([y[5] for y in x])\ndef imax0(x):\n    return np.argmax([y[0] for y in x])\ndef imin0(x):\n    return np.argmin([y[0] for y in x])\ndef imax1(x):\n    return np.argmax([y[1] for y in x])\ndef imin1(x):\n    return np.argmin([y[1] for y in x])\ndef imax2(x):\n    return np.argmax([y[2] for y in x])\ndef imin2(x):\n    return np.argmin([y[2] for y in x])\ndef imax3(x):\n    return np.argmax([y[3] for y in x])\ndef imin3(x):\n    return np.argmin([y[3] for y in x])\ndef imax4(x):\n    return np.argmax([y[4] for y in x])\ndef imin4(x):\n    return np.argmin([y[4] for y in x])\ndef distance_comparison(df,start_point,end_point,number_of_jockies):\n    dis=df[start_point:end_point].iloc[:,5:number_of_jockies+5-1]\n    disT=dis.T\n    disTP=disT[disT>0]\n    disTPT=disTP.T\n    LDF=disTPT.max(axis=1).max()\n    SDF=disTPT.max(axis=1).min()\n    dis=df[start_point:end_point].iloc[:,5:number_of_jockies+5-1]\n    disT=dis.T\n    disTP=disT[disT<0]\n    disTPT=disTP.T\n    LDB=disTPT.min(axis=1).min()\n    SDB=disTPT.min(axis=1).max()\n    return LDF,SDF,LDB,SDB\ndef window(df,col):\n    #dfP=pd.DataFrame({'distance':df})\n    df['window']=df[col].rolling(30).mean()\n    return df\ndef X_Y_Z(df,lat,long):\n    R=6371\n    X=[]\n    Y=[]\n    Z=[]\n    latdfx=df[lat].tolist()\n    londfy=df[long].tolist()\n    for lat,lon in zip(latdfx,londfy):\n        x = R * math.cos(lat) * math.cos(lon)\n\n        y = R * math.cos(lat) * math.sin(lon)\n\n        z = R *math.sin(lat)\n        X.append(x)\n        Y.append(y)\n        Z.append(z)\n    return X,Y,Z\ndef distance2(df):\n    distance=[]\n    speed=[]\n    accelerate=[]\n    lan_log=np.array([df[5].values, df[6].values]).T.tolist()\n    for i in range(len(lan_log)-1):\n        lat1, lon1 = lan_log[i]\n        lat2, lon2 = lan_log[i+1]\n        radius = 6371 # km\n\n        dlat = math.radians(lat2-lat1)\n        dlon = math.radians(lon2-lon1)\n        a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \\\n            * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)\n        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))\n        d = radius * c\n        distance.append(d)\n    for i in range(len(distance)):\n        speed.append((distance[i])/0.25)\n    for i in range(len(speed)-1):\n        accelerate.append((speed[i+1]-speed[i])/0.25)\n    return distance,speed,accelerate\ndef distance(df,df1):\n    distance=[]\n    speed=[]\n    accelerate=[]\n    lan_log=np.array([df[5].values, df[6].values]).T.tolist()\n    lan_log2=np.array([df1[5].values, df1[6].values]).T.tolist()    \n    for i in range(len(lan_log)):\n        lat1, lon1 = lan_log[i]\n        lat2, lon2 = lan_log2[i]\n        radius = 6371 # km\n\n        dlat = math.radians(lat2-lat1)\n        dlon = math.radians(lon2-lon1)\n        a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \\\n            * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2)\n        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))\n        d = radius * c\n        distance.append(d)\n    for i in range(len(distance)):\n        speed.append((distance[i])/0.25)\n    for i in range(len(speed)-1):\n        accelerate.append((speed[i+1]-speed[i])/0.25)\n    return distance,speed,accelerate\n\ndef prepare_data_of_a_game(data,track,date,time):\n    here='URL'\n    pass_this_game=''\n    pass_this_game2=''\n    race=data[(data[0]==track)&(data[1]==date)&(data[13]==time)]\n    names_jockies=race[[15,17]].sort_values(by=17).drop_duplicates()\n    names_jockies=names_jockies[15].tolist()\n    ListDF=[]\n    yees=0\n    Noo=0\n\n    for i in names_jockies:\n        ListDF.append(race[race[15]==i][[4,5,6]].sort_values(4))\n\n    for l,j in enumerate(ListDF):\n        for i in ListDF:\n            if len(i)!=len(j):\n                print('Size of data is not the same, it seems some track ids are missed')\n                pass_this_game='yes'\n                ListDF=[]\n    for i in range(1,len(ListDF)+1):\n        for j in range(1,len(ListDF)+1):\n            if i<j:\n                distance1,speed,accelerate =distance(ListDF[i-1],ListDF[j-1])\n                ListDF[i-1]['distance'+str(i)+'.'+str(j)]=distance1\n                ListDF[j-1]['distance'+str(j)+'.'+str(i)]=distance1\n    for i in range(1,len(ListDF)+1):\n                distance1,speed,accelerate =distance2(ListDF[i-1])\n                ListDF[i-1]['distance'+str(i)+str(i)]=[0]+distance1\n                ListDF[i-1]['speed']=[0]+speed\n                ListDF[i-1]['accelerate']=[0,0]+accelerate    \n    for i in range(len(ListDF)):\n        X,Y,Z=X_Y_Z(ListDF[i],5,6)\n        ListDF[i]['X']=X\n        ListDF[i]['Y']=Y\n        ListDF[i]['Z']=Z\n    for i in range(len(ListDF)):\n        if ListDF[i]['X'].values[4]>ListDF[i]['X'].values[5]:\n            yees=yees+1\n        if ListDF[i]['X'].values[4]<ListDF[i]['X'].values[5]:\n            Noo=Noo+1\n    if yees!=len(ListDF) and Noo!=len(ListDF):\n        pass_this_game2='yes'\n        print(f\"Unfortunately, this game can not be analysied. Becouse there is a problem in the given latitude and longitude. Please check {here} to get more information. \")\n\n    return ListDF,pass_this_game,pass_this_game2","metadata":{"execution":{"iopub.status.busy":"2022-12-03T01:10:56.745756Z","iopub.execute_input":"2022-12-03T01:10:56.746174Z","iopub.status.idle":"2022-12-03T01:10:56.923315Z","shell.execute_reply.started":"2022-12-03T01:10:56.746133Z","shell.execute_reply":"2022-12-03T01:10:56.922100Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"##  **Classifying the shape of the track**\n\nFor this analysis the tracks have been classified in three following groups as below:\n\n* Elipsoide Shape\n*  Half Elipsoide Shape\n* A-Part Elipsoide Shape\n\n##### **Elipsoide Shape**: \nIf the graph of the race is an elipsoide shape, we call it **Elipsoide Shape**. \n\n##### **Half Elipsoide Shape**:\nIf the graph of the race is a U shape, basically half or more than half of an elipsoide, we call it **Half Elipsoide Shape**.\n\n#####  **A-Part Elipsoide**\nIf the graph is a part of an elipsoide but it doesn't have a U shape we call it **A-Part Elipsoide**. \n\n**An example of each shape has been shown in the following graphs:**","metadata":{}},{"cell_type":"code","source":"Elipsoide_Shape,r1,r2=prepare_data_of_a_game(data,'BEL','2019-04-28',308)\nHalf_Elipsoide_Shape,r1,r2=prepare_data_of_a_game(data,'BEL','2019-04-26',130)\nA_Part_Elipsoide,r1,r2=prepare_data_of_a_game(data,'BEL','2019-04-27',518)\nf = plt.figure(figsize=(16,5))   \n\nf.tight_layout(pad=8)\nf.add_subplot(1,3, 1)\n# using padding\n\nplt.plot(Elipsoide_Shape[0][5], Elipsoide_Shape[0][6], color='y', label='Elipsoide Shape')\nplt.title('Elipsoide Shape')\nf.add_subplot(1,3, 2)\nplt.plot(Half_Elipsoide_Shape[0][5], Half_Elipsoide_Shape[0][6], color='y', label='Half Elipsoide Shape')\nplt.title('Half Elipsoide Shape')\nf.add_subplot(1,3, 3)\nplt.plot(A_Part_Elipsoide[0][5], A_Part_Elipsoide[0][6], color='y', label='A-Part Elipsoide')\nplt.title('A-Part Elipsoide Shape')\nplt.show(block=True)\n\n\n#ax.scatter3D(XBB2[i],YBB2[i] ,ZBB2[i],facecolor=\"blue\")\n\n# ax = plt.axes(projection='3d')\n# f0 = plt.figure(figsize=(15,5))\n# #ax = plt.axes(projection='3d')\n# ax.scatter3D(Elipsoide_Shape[0]['X'],Elipsoide_Shape[0]['Y'] ,Elipsoide_Shape[0]['Z'],facecolor=\"yellow\")\n\n# # f0.add_subplot(1,3, 2)\n# ax = plt.axes(projection='3d')\n# ax.scatter3D(Half_Elipsoide_Shape[0]['X'],Half_Elipsoide_Shape[0]['Y'] ,Half_Elipsoide_Shape[0]['Z'],facecolor=\"yellow\")\n\n# f0.add_subplot(1,3, 3)\n# ax = plt.axes(projection='3d')\n# ax.scatter3D(Two_Part_Elipsoide[0]['X'],Two_Part_Elipsoide[0]['Y'] ,Two_Part_Elipsoide[0]['Z'],facecolor=\"yellow\")\n\n# plt.show(block=True)\n","metadata":{"execution":{"iopub.status.busy":"2022-12-03T01:10:56.925918Z","iopub.execute_input":"2022-12-03T01:10:56.926303Z","iopub.status.idle":"2022-12-03T01:11:00.003753Z","shell.execute_reply.started":"2022-12-03T01:10:56.926268Z","shell.execute_reply":"2022-12-03T01:11:00.002745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Using Cartesian Coordinates to find a measure for determining the position of jockeys with respect of each other**","metadata":{}},{"cell_type":"markdown","source":"We need a **measure** to understant which jockey is **further** in the track. The distance function in the above gives us the distance between jockies but it dosn't tell which jocky is further. In order to find a measure to compare **positions** of jockies with respect of each othe, we need to convert latitude and longitude to **cardisian coordinates** (X,Y,Z) in R^3. It is actually a two dimention surface in R^3. The **critical points** of the track's shape play an important role to find this measure. We describe what they are and how to find them in the following.\n\n### **Critial Points Of a Track**\n\nWe define **critical points** of a track as some points where the **gradian** of the surface is **zero**. For an example, a 2D elipsoide has two critical point. \n\n\n\n\n\n\n\n\n\n\n![Capture.PNG](attachment:50d8bc81-6c54-475e-8577-53378e3bcb44.PNG)\n\n\nIn this data set two races `SAR` and `AQU` races look like the ellipsoid in the **left** hand side (in the **above picture**) and `BEL` track looks like the **right** hand side. Depending on the shape of the track, a track has **at most two** critical points and **at least one.** The **Ellipsoid Shape** track has **two** critical points, the **Half Ellipsoid** shape track has **one** critical point and **A_parts Elipsoide** shape almost **starts** with a critical point and has **one more** critical point.\n\n### **How critical points help to find the positions of jockeys?** \n\nThe critical point of a track is a point very close to red points in the above pictures. In the `BEL` race, before this point if X-coordiante of  `jocky A ` is bigger than `jocky B`, then `Jocky A` is furthur. And after this point, if `X`-coordinate of  `jocky A ` is bigger than `jocky B`, then `Jocky B` is furthur.\nIn the `AQU` and `SAR` races, the same thing happen with `Y` axis. \n","metadata":{},"attachments":{"50d8bc81-6c54-475e-8577-53378e3bcb44.PNG":{"image/png":"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"}}},{"cell_type":"markdown","source":"# How to find critical points of jockeys?\n\nIn the `BEL` race, from the beining of the race until a point very close to the critical point, the `X`-coordinates of each jocky is **increasing** (or decreasing, depends on the game). After this point the trend of `X`-coordinate changes to **decreasing** (or increasing). Let's call this point **first_D_CH**.\n\nIf the track has **two critical points**, the same thing happens with the secend critical point.  \n\nTo **compare** the **position** of jockies with respect of each other we do the following:\n\n* determine first_D_CH of jockey A and jocky B. \n* - pick the smaller one and get 5 track_id after and 5 track_id before this index.\n* - If the sign of difference between X-coordinates of jockies A and B changed once between these 10 indecies, the index of the row that sign changes is a critical point.\n* - I the sign doesn't change at all, the smaller first_D_CH of jockies A and B is the critical point.\n* - If the sign changes morre than once in these 10 coordinates, the smaller first_D_CH of jockies A and B is the critical point.\n\nLet's see some examples: Consider the game in track `BEL` in date 2019-05-23 at 6:25. Let's compare the jocky with first end position ` 'Jose L. Ortiz'` and the jocky with second end position `Jose Lezcano` and the jocky with th 5-th end position `Joel Rosario`. \nA new dataframe `Compare_coordinates` has been created with the following columns:\n- `first_X`: X coordinates of the jocky with the first end position\n- `second_X`: X coordinates of the jocky with the second end position\n- `fifth_X`: X coordinates of the jocky with the fifth end position\n- `diff_12`: The difference between X coordinates of the first and the second jockey.\n- `diff_15`: The difference between X coordinates of the first and the fifth jockey.\n\nAs it has been printed in the following, the X-coordinates of all three jockies is increasing until `170-th` row for the first jocky, `171-th` row for the second jocky and the `172-th` position for the `5-th` jocky. But if we look at the columns `diff_12` and `diff_15` which is the difference of X-coordinates of first jocky and the second jocky and the first jocky with the fifth jocky respectively, you can see that values of `diff_12` are negative until the row 172 and after that is positive (which means that the first jocky was further after and before this critical point). The values of `diff_15` has an opposite trend. The critical point is 173-th row, and the fifth jocky was further before and after this point.\n\n\n","metadata":{}},{"cell_type":"code","source":"BEL5=data[(data[0]=='BEL')&(data[1]=='2019-05-23')&(data[13]==625)]\nBB1=BEL5[BEL5[15]=='Jose L. Ortiz'][[4,5,6]].sort_values(4)\nBB2=BEL5[BEL5[15]=='Jose Lezcano'][[4,5,6]].sort_values(4)\nBB5=BEL5[BEL5[15]=='Joel Rosario'][[4,5,6]].sort_values(4)\nXBB1,YBB1,ZBB1=X_Y_Z(BB1,5,6)\nXBB2,YBB2,ZBB2=X_Y_Z(BB2,5,6)\nXBB5,YBB5,ZBB5=X_Y_Z(BB5,5,6)\ndiff15=[]\ndiff12=[]\nfor i,j,k in zip(XBB1,XBB2,XBB5):\n    diff15.append(i-k)\n    diff12.append(i-j)\nCompare_coordinates=pd.DataFrame({'first_X':XBB1,'second_x':XBB2,'fifth_X':XBB5, 'diff_12':diff12, 'diff_15':diff15})\nCompare_coordinates[150:210]","metadata":{"execution":{"iopub.status.busy":"2022-12-03T01:11:00.006745Z","iopub.execute_input":"2022-12-03T01:11:00.007585Z","iopub.status.idle":"2022-12-03T01:11:00.752700Z","shell.execute_reply.started":"2022-12-03T01:11:00.007542Z","shell.execute_reply":"2022-12-03T01:11:00.751757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### The following function find the position of jockeys in each track ids.","metadata":{}},{"cell_type":"code","source":"\n\ndef get_index(df,col_difference,race):\n    if race=='BEL':\n        col='X'\n    if race=='AQU' or race=='SAR':\n        col='Y'\n    if df[col].values[4]>df[col].values[5]:\n        df[col]=df[col]*-1\n    secend_critical_p=''\n    df=df.reset_index()\n    g=df[col].diff(-1)\n    idx=g[g>0].index[0]\n    #print(idx)\n    if len(g[idx:][g<0])!=0:\n        idx2=g[idx:][g<0].index[0]\n        secend_critical_p='yes'\n    else:\n        idx2=''\n    #print(idx,idx2)\n    tmp = np.sign(df.iloc[max(idx-10,0):idx+11][col_difference]).diff().dropna().ne(0)\n    if tmp.sum() == 1:\n        idx=tmp[tmp].index.item()\n    if secend_critical_p=='yes':\n        tmp = np.sign(df.iloc[max(idx2-10,0):idx2+11][col_difference]).diff().dropna().ne(0)\n        if tmp.sum() == 1:\n            idx2=tmp[tmp].index.item()\n\n    return idx,idx2\n\n\n\n# This function find th position of each jockey in each track\ndef find_point(dflist,race):\n    positions=pd.DataFrame()\n    if race=='BEL':\n        col='X'\n    if race=='AQU' or race=='SAR':\n        col='Y'\n    for df in dflist:\n        if df[col].values[4]>df[col].values[5]:\n            df[col]=df[col]*-1   \n            #print(t)\n    for k  in range(1,len(dflist)+1):\n        for t in range(1,len(dflist)+1):\n            if k!=t:\n                dflist[k-1]['df'+str(k)+str(t)]=dflist[t-1][col].tolist()\n                dflist[k-1]['diff'+'df'+str(k)+str(t)]=-dflist[k-1][col]+dflist[k-1]['df'+str(k)+str(t)]\n    for k  in range(1,len(dflist)+1):\n        for t in range(1,len(dflist)+1):\n            if k!=t and k<t:\n                a,b=get_index(dflist[k-1],'diff'+'df'+str(k)+str(t),race)\n                a1,b1=get_index(dflist[t-1],'diff'+'df'+str(t)+str(k),race)\n                mina=min([a,a1])\n                zeroz=len(dflist[k-1])*[0]\n                zeroz[mina:]=(len(zeroz)-mina)*[1]\n                dflist[k-1]['direction'+str(k)+str(t)]=zeroz\n                dflist[t-1]['direction'+str(t)+str(k)]=zeroz\n\n                if b!='' and b1!='':\n                    minb=min([b,b1])\n                    zeroz=len(dflist[k-1])*[0]\n                    zeroz[minb:]=(len(zeroz)-minb)*[0]\n                    dflist[k-1]['direction'+str(k)+str(t)]=zeroz\n                    dflist[t-1]['direction'+str(t)+str(k)]=zeroz\n    for k  in range(1,len(dflist)+1):\n        for t in range(1,len(dflist)+1):\n            if k!=t :\n                dflist[k-1]['positin'+str(k)+'.'+str(t)] = dflist[k-1]['direction'+str(k)+str(t)].sub(dflist[k-1]['diff'+'df'+str(k)+str(t)].gt(0)).abs()\n                positions['positin'+str(k)+'.'+str(t)]=dflist[k-1]['positin'+str(k)+'.'+str(t)].tolist()\n\n                dflist[k-1].loc[dflist[k-1]['positin'+str(k)+'.'+str(t)]==1, 'distance'+str(k)+'.'+str(t)] = dflist[k-1].loc[dflist[k-1]['positin'+str(k)+'.'+str(t)]==1, 'distance'+str(k)+'.'+str(t)]*(-1)                \n    for i in range(1,len(dflist)+1):\n        positions[str(i)+'th']=positions.iloc[:,(i-1)*(len(dflist)-1):(i)*(len(dflist)-1)].sum(axis=1)\n    return dflist,positions","metadata":{"execution":{"iopub.status.busy":"2022-12-03T01:11:00.753793Z","iopub.execute_input":"2022-12-03T01:11:00.754294Z","iopub.status.idle":"2022-12-03T01:11:00.780139Z","shell.execute_reply.started":"2022-12-03T01:11:00.754259Z","shell.execute_reply":"2022-12-03T01:11:00.779221Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Visualization:**\n\nUsing the above method the **following graph** shows the **position** of jockeys in each **track_id**.\nThere are **6** jockeys in this competition. The **x-axis** is **track ids** and **y-axis** is the **positions**. **line zero** shows the **first** position and **line 5th** shows the **last** position. For example at the beginning of the race the brown colour jockey is further than others (his end position is 4)\nYou can see the jockey with the first end position (green colour) is not in the first position before somewhere around 360th track id. ","metadata":{}},{"cell_type":"code","source":"# Visualization of jockeys' positions\nL,pass_game,kkk=prepare_data_of_a_game(data,\"BEL\",'2019-04-28',308)\nf0,positions=find_point(L,'BEL')\npositions1=positions.reset_index()\nax1 = positions1.plot(kind='scatter', x='index', y='1th', color='red',figsize=(16,8)) \nfor i,j in zip(range(1,len(L)+1),['green','blue','yellow','brown','black','pink']):   \n    ax2 = positions1.plot(kind='scatter', x='index', y=str(i)+'th', color=j, ax=ax1,figsize=(25,18),label=str(i)+'th end position') ","metadata":{"execution":{"iopub.status.busy":"2022-12-03T01:11:00.781973Z","iopub.execute_input":"2022-12-03T01:11:00.782343Z","iopub.status.idle":"2022-12-03T01:11:02.616201Z","shell.execute_reply.started":"2022-12-03T01:11:00.782300Z","shell.execute_reply":"2022-12-03T01:11:02.615082Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":" ","metadata":{}},{"cell_type":"markdown","source":"# **Track division description**\n\nIn the **Main_Algorithm**, the track has been divided to some pieces and analysing the game has been done in each part in detail. The **number** of pieces depends on the **shape** of the track. Before describing this devision we need two more definitions.\n\nIn the `BEL` shape where we use `X` coordinates to find critical points, we can use **latitude coordinates** to find points where the jockey enters to the **corner** of the track. Basically, we define two more points, one **before** the critical point and one **after** that. We determine them with the following method:\n\n* choose the first point where the trend of latitude changes. This is the first point. We call it FBP. \n* find the difference between track_ids of FBP and the critical point. \n* add this amount to the critical point to find the second point. We call it SBP\n\nIf the race is `SAR` or `AQU` we do the same thing by **longitude coordinates**. Also, if the track has **two** critical point we do the same thing to find `FBP2` and `SBP2`. Again if the **geometry** of the coordinates are not clear for you, use the above **website** to make sure this **measure** is **accurate**. \n\n\n\n","metadata":{}},{"cell_type":"markdown","source":"\n\n### **Describing track devision for each track shape:**\n\n\n> #### **Elipsoide Shape**\n\n* First_Straight_Way: From the point that the jockey starts until the `FBP` point.\n* First_Corner: From `FBP` point to the first critical point.\n* Second_Corner: From the first critical point to the `SBP` point.\n* Second_Straight_Way: From the `SBP` point to the `FBP2` point.\n* Third_Corner: From the `FBP2` point to the second critical points.\n* Forth_Corner: From the second critical point to the `SBP2` point.\n* Third_Straight_Way: From `SBP2` point to the rest of the race\n\n\n> #### **Half Elipsoide Shape**\n\n* First_Straight_Way: where the jockey start until the `FBP` point.\n* First_Corner: From `FBP` point to the first critical point.\n* Second_Corner: From the first critical point to the `SBP` point.\n* Second_Straight_Way: From the `SBP` point to the `FBP2` point.\n\n\n> ####  **A-Part Elipsoide** \n\n* Second_Corner: From the first critical point to the `SBP` point.\n* Second_Straight_Way: From the `SBP` point to the `FBP2` point.\n* Third_Corner: From the `FBP2` point to the second critical points.\n* Forth_Corner: From the second critical point to the `SBP2` point.\n* Third_Straight_Way: From `SBP2` point to the rest of the race\n","metadata":{}},{"cell_type":"code","source":"def finding_corners_interval(L,race,positions):\n        jockeys_dis=[]\n        #print(race)\n        #f,positions=find_point(L,'BEL')\n        #s,d,t,u=finding_corners_interval(L)\n    #     game_data=data[(data[0]=='BEL')&(data[1]=='2019-10-14')&(data[13]==332)]\n    #     if game_data[17].value_counts().drop_duplicates().shape[0]!=1:\n    #         print(f\"Sorrry!!!!! Since the length of track_ids are not equal for all jockies, no analysis can be provided for this horse racing. Please choose a different game. For example the track_ids of jockies with the end positions {list(game_data[17].value_counts().drop_duplicates().index)} are not the same.\")\n        if race=='BEL':\n            col='X'\n            col2=5\n        if race=='AQU':\n            col='Y'\n            col2=6\n        if race=='SAR':\n            col='Y'\n            col2=6        \n        end_point=len(L[0])\n#     geolocator = Nominatim(user_agent=\"coordinateconverter\")\n#     location1 = geolocator.reverse(\"40.715902,-73.720118\")\n#     location = geolocator.reverse(f\"{L[0][5].values[0]},{L[0][6].values[0]}\")\n#     print(location.address)\n#     print(L[0].head(1))\n#     if location.address!=location1.address:\n#         print(f\"OPS, there is an error in the data set for this horse racing. The location is BEL in the data set but it has been happened in {location.address}. For this reason, unfortuently, there is no analysis for this game. Please try other games.\")\n\n#     if location.address==location1.address:\n        ind=0\n        k=0\n        FP_jockey=[]\n        max_k=0\n        for j in range(L[0].shape[0]-1,len(L[0])-70,-1):\n            #print(f\"iiiiiiiiiiiiiiiiiiiiiiiiiiiii {j,k,ind}\")\n            if max_k<k:\n                max_k=k\n                ind=j\n                #print(j,k,ind)\n            k=0\n            for i in range(2,len(L)+1):\n                    if positions[str(i-1)+'th'].values[j]+1==positions[str(i)+'th'].values[j]:\n                        k=k+1\n            if k==len(L)-1:\n                ind=j\n                break\n                        \n        if ind<len(L[0]):\n            print(f\"There are {len(L[0])} track_ids  for this game. But it seems the game ended in the {ind}th track_id. So all analysis are based on the first {ind} track_ids.\")\n            for k in range(len(L)):\n                L[k]=L[k][:ind]\n                end_point=ind\n            for i in range(2,len(L)):\n                if positions[str(i-1)+'th'].values[ind]+1!=positions[str(i)+'th'].values[ind] or positions[str(i)+'th'].values[ind]+1!=positions[str(i+1)+'th'].values[ind]:\n                    FP_jockey.append(i)\n                    #print(f'injjjjjjjjjjjjjjjjjjjjjjjjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {i}')\n                    #print(f'injjjjjjjjjjjjjjjjjjjjjjjjaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa {i}')\n            if len(FP_jockey)==2:\n                end_positions=game_data.drop_duplicates(subset=[15])\n                end_positions1=end_positions[17][end_positions[17].duplicated()]\n                if end_positions1.shape[0]!=0:\n                    if end_positions1.shape[0]==1:\n                            print(f\" There are two jockies with the end position {end_positions1.values[0]} in this game.\")\n                            if FP_jockey[0]!=end_positions1.values[0] and FP_jockey[1]!=end_positions1.values[0]:\n                                print(f\"It seems that not all final end positions of jockies are accurate in this game. The jocky with the end position {FP_jockey[0]} should be in {FP_jockey[1]} position and vice versa. To check if this statments is true please check the given latitude and longitude of these jockies in this website: https://www.sunearthtools.com/tools/distance.php \")\n                                print(f\"The latitude and the longitude of {game_data[game_data[17]==FP_jockey[0]][15].values[ind]} is ({game_data[5].values[ind],game_data[6].values[ind]} and the latitude and the longitude of {game_data[game_data[17]==FP_jockey[1]][15].values[ind]} is ({game_data[5].values[ind],game_data[6].values[ind]})\")\n            #print(f'faaaaaaaaaaaaaaaaaallllllllllseeeeeeeeeppppppppppppppppppppp {FP_jockey}')\n            if len(FP_jockey)>2:\n                print('The final end position of jockies are not accure. this game can not be analyzed')\n        third_corner=range(10000,10001)\n        first_corner=range(10000,10001)\n        forth_corner=range(10000,10001)\n        third_straight_way=range(10000,10001)\n        first_straight_way=range(10000,10001)\n        second_straight_way=range(10000,10001)\n\n        here='URL'\n        for i in range(len(L)):\n            L[i]=L[i].reset_index()\n            L[i]['count']=np.where(np.sign(L[i]['accelerate']).diff().eq(0),np.nan,1)\n            L[i]['count']=L[i]['count'].cumsum().ffill()\n\n            # groupby to take count of each group of rows and return groupsize using transform\n            L[i]['count']=L[i].groupby('count')['accelerate'].transform('size')*np.sign(L[0]['accelerate'])\n\n        second_lat_point=''\n        first_lat_point=0\n        idx2=''\n        for i in range(len(L)):\n            jocky_result=[]\n            if col=='X':\n                if L[i][col].values[24]>L[i][col].values[25]:\n                    L[i][col]=L[i][col]*-1\n                    #print('doooooooooooooooooonnnnnnnnnnttttttttttt')\n            if col=='Y':\n                if L[i][col].values[24]>L[i][col].values[25]:\n                    L[i][col]=L[i][col]*-1                \n            secend_critical_p=''\n            L[i]=L[i].reset_index()\n            g=L[i][col].diff(-1)\n            g=g[24:]\n            idx=g[g>0].index[0]\n            #print(idx)\n            if len(g[idx:][g<0])>20:\n                if g[idx:][g<0].index[1]-g[idx:][g<0].index[0]>60:\n                    idx2=g[idx:][g<0].index[1]\n                    secend_critical_p='yes'\n                else:\n                    idx2=g[idx:][g<0].index[0]\n                    secend_critical_p='yes'\n            if L[i][col2][4:5].values[0]-L[i][col2][5:6].values[0]<0:\n                L[i][col2]=L[i][col2]*-1\n            gg1=L[i][col2][5:].diff(1)\n            if np.var(list(gg1[gg1>0].index)[:10])<50:\n                NUM=list(gg1[gg1>0][0:1].index)[0]\n            else:\n                for v in range(10):\n                    var=np.var(list(gg1[gg1>0].index)[v:v+4])\n                    if var<50:\n                        indV=v\n                        break\n                NUM=list(gg1[gg1>0][indV:indV+1].index)[0]       \n\n\n            if NUM<200:\n                first_lat_point=NUM\n                symmetry=idx-first_lat_point\n                second_area=idx+symmetry\n                first_straight_way=range(0,first_lat_point) \n                first_corner=range(first_lat_point,idx)\n                second_corner=range(idx,second_area)\n            else:\n                second_area=idx+30\n                second_corner=range(idx,second_area)\n                #print(f\"This track dosn't have the First_Corner part. For more information please see {here}\")\n            #print(idx2)\n            if idx2=='':\n                second_straight_way=range(second_area,len(L[i]))\n            if idx2!='' :\n                if first_lat_point!=0:\n                    if len(gg1[first_lat_point:][gg1<0])>20:\n                        second_lat_point=gg1[first_lat_point:][gg1<0].index[0]\n                        secend_critical_p='yes'\n                        symmetry2=abs(idx2-second_lat_point)\n                        forth_area=idx2+symmetry2\n                        third_corner=range(second_lat_point,idx2)\n                        forth_corner=range(idx2,forth_area) \n                        second_straight_way=range(second_area,second_lat_point)\n                        third_straight_way=range(forth_area,len(L[i]))\n\n                if first_lat_point==0:\n                    if len(gg1[200:][gg1>0])!=0:\n                        second_lat_point=gg1[200:][gg1>0].index[0]\n                        secend_critical_p='yes'\n                        symmetry2=idx2-second_lat_point\n                        forth_area=idx2+symmetry2\n                        third_corner=range(second_lat_point,idx2)\n                        forth_corner=range(idx2,forth_area) \n                        second_straight_way=range(second_area,second_lat_point)\n                        third_straight_way=range(forth_area,len(L[i]))\n\n            #print(f\"first lat: {first_lat_point}, first_critical:{idx}, second_lat:{second_lat_point}, second_critical:{idx2},first_straight_way:{first_straight_way}, first corner:{first_corner},second corner:{second_corner}, second_straight_way: {second_straight_way},third corner :{third_corner}, forth corner:{forth_corner}, third_straight_way:{third_straight_way}\")\n            #print('\\n')\n            the_number_of_increasing_accel_in_row=L[i][['count']].max().values[0]\n            the_number_of_decreasing_accel_in_row=L[i][['count']].min().values[0]\n            starting_point_of_increasing=L[i][['count']].idxmax().values[0]\n            starting_point_of_decreasing=L[i][['count']].idxmin().values[0]\n            end_point_of_increasing=L[i][['count']].idxmax().values[0]+L[i][['count']].max().values[0]\n            end_point_of_decreasing=L[i][['count']].idxmin().values[0]-L[i][['count']].min().values[0]\n            #print(f'This jocky had {sum(L[i]['accelerate']<0)} negative accelerate.')\n            #print(f\"The accepoint leration has increased in {the_number_of_increasing_accel_in_row} track_id in a row (from {starting_point_of_increasing} track_id to {end_point_of_increasing}).\")\n            #print(f\"The acceleration has decreased in {the_number_of_decreasing_accel_in_row} track_id in a row (from {starting_point_of_decreasing} track_id to {end_point_of_decreasing}).\")\n            #print('The avrage speeds of this jocky in different part of the track are as follow')\n            #print('\\n')\n\n            if 10000  in third_corner and 10000 not in first_straight_way:\n                race_shape='half_elipsoide'\n                starting_points=[first_straight_way[0],first_corner[0],second_corner[0],second_straight_way[0],1000,1000,1000]\n                end_points=[first_straight_way[-1]+1,first_corner[-1]+1,second_corner[-1]+1,second_straight_way[-1]+1,1001,1001,1001]\n                race_partsN=4\n            if 10000 not in third_corner:\n                race_shape='elipsoide'\n                starting_points=[first_straight_way[0],first_corner[0],second_corner[0],second_straight_way[0],third_corner[0],forth_corner[0],third_straight_way[0]]\n                end_points=[first_straight_way[-1]+1,first_corner[-1]+1,second_corner[-1]+1,second_straight_way[-1]+1,third_corner[-1]+1,forth_corner[-1]+1,third_straight_way[-1]+1]\n                race_partsN=7\n            if 10000 in first_straight_way:\n                race_shape='2_part_elipsoide'\n                starting_points=[1000,1000, second_corner[0],second_straight_way[0],1000,1000,1000]\n                end_points=[1001,1001,second_corner[-1]+1,second_straight_way[-1]+1,1001,1001,1001]\n                race_partsN=2\n       \n            if 10000 in first_straight_way and 1000 not in third_corner:\n                race_shape='5_part_elipsoide'\n                starting_points=[1000,1000,second_corner[0],second_straight_way[0],third_corner[0],forth_corner[0],third_straight_way[0]]\n                end_points=[1001,1001,second_corner[-1]+1,second_straight_way[-1]+1,third_corner[-1]+1,forth_corner[-1]+1,third_straight_way[-1]+1]\n                race_partsN=6\n       \n    \n            race_parts=['First_Straight_Way','First_Corner','Second_Corner','Second_Straight_Way','Third_Corner','Forth_Corner','Third_Straight_Way']\n\n            for r,k , p in zip(race_parts,starting_points,end_points):\n                speed=L[i][k:p]['speed'].mean()\n                positions_min=positions[str(i+1)+'th'][k:p].min()\n                #print(f\"herrrrrrrrrrrrrrrrrrrrrrrrrrreeeeeeeeeeeeeeeeee {positions_min}\")\n                positions_max=positions[str(i+1)+'th'][k:p].max()\n                LDF,SDF,LDB,SDB=distance_comparison(L[i],k,p,len(L))\n                jocky_result.append([r,LDF,SDF,LDB,SDB,speed,positions_min,positions_max])\n            \n            jockeys_dis.append(jocky_result)\n\n\n        return jockeys_dis,race_partsN,race_shape,starting_points,end_points,race_parts,ind","metadata":{"execution":{"iopub.status.busy":"2022-12-03T01:11:02.617986Z","iopub.execute_input":"2022-12-03T01:11:02.619004Z","iopub.status.idle":"2022-12-03T01:11:02.670970Z","shell.execute_reply.started":"2022-12-03T01:11:02.618958Z","shell.execute_reply":"2022-12-03T01:11:02.669940Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nL,pass_game,kkk=prepare_data_of_a_game(data,\"AQU\",'2019-04-12',515)\nf,positions=find_point(L,'AQU')\njockeys_dis,race_partsN,race_shape,starting_points,end_points,race_parts,ind=finding_corners_interval(L,'AQU',positions)","metadata":{"execution":{"iopub.status.busy":"2022-12-03T01:11:02.672290Z","iopub.execute_input":"2022-12-03T01:11:02.672694Z","iopub.status.idle":"2022-12-03T01:11:04.266614Z","shell.execute_reply.started":"2022-12-03T01:11:02.672660Z","shell.execute_reply":"2022-12-03T01:11:04.265583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **The following graphs shows the track division for three defined shapes**","metadata":{}},{"cell_type":"code","source":"f = plt.figure(figsize=(16,5))\n\nf.tight_layout(pad=8)\nf.add_subplot(1,3, 1)\n# using padding\nL,pass_game,kkk=prepare_data_of_a_game(data,\"BEL\",'2019-04-28',308)\nf0,positions=find_point(L,'BEL')\njockeys_dis,race_partsN,race_shape,starting_points,end_points,race_parts,ind=finding_corners_interval(L,'BEL',positions)\n\nfor i,j,k,o in zip(starting_points,end_points,['r','blue','g','y','black','brown','pink'],race_parts):\n    if i!=1000:\n        plt.plot(L[0]['X'][i:j], L[0]['Y'][i:j], color=k, label=o)\n        plt.legend()\nplt.title('Elipsoide Shape')  \nf.add_subplot(1,3, 2)\nL,pass_game,kkk=prepare_data_of_a_game(data,\"BEL\",'2019-04-26',130)\nf0,positions=find_point(L,'BEL')\njockeys_dis,race_partsN,race_shape,starting_points,end_points,race_parts,ind=finding_corners_interval(L,'BEL',positions)\nfor i,j,k,o in zip(starting_points,end_points,['r','blue','g','y','black','brown','pink'],race_parts):\n    if i!=1000:\n        plt.plot(L[0]['X'][i:j], L[0]['Y'][i:j], color=k, label=o)\nplt.legend()\nplt.title('Half Elipsoide Shape')\nf.add_subplot(1,3, 3)\nL,pass_game,kkk=prepare_data_of_a_game(data,\"BEL\",'2019-04-27',518)\nf0,positions=find_point(L,'BEL')\njockeys_dis,race_partsN,race_shape,starting_points,end_points,race_parts,ind=finding_corners_interval(L,'BEL',positions)\nfor i,j,k,o in zip(starting_points,end_points,['r','blue','g','y','black','brown','pink'],race_parts):\n    if i!=1000:\n        plt.plot(L[0]['X'][i:j], L[0]['Y'][i:j], color=k, label=o)\n        plt.legend()\nplt.title('A-Part Elipsoide Shape')\nplt.show(block=True)\n\n\n\n\n\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2022-12-03T01:11:04.268001Z","iopub.execute_input":"2022-12-03T01:11:04.268604Z","iopub.status.idle":"2022-12-03T01:11:08.991611Z","shell.execute_reply.started":"2022-12-03T01:11:04.268567Z","shell.execute_reply":"2022-12-03T01:11:08.990472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Main Algorithm**\n\nAn **intelligent algorithm** has been developed to analyse the performance of each jockey in each game. It is imposible to go through the **details** of the algorithm since it contains many **statistics** and **competitive analysis** to make the right decision in different circumstances.\n\nA **new data set** has been created and uploaded in this notebook (`All_Jockeys_data.csv`). It contains information about distance/speed/position and some other information about each jockey and game. This information is used in statistical models in the decision making process.\n\n### The Input and Output of The Main Algorithm:\n\n> **Input; It takes four inputs as below:**\n\n* `All_Jockeys_data` data set \n* The name of the race (there are 3 options: `BEL`, `SAR`, `AQU`)\n* The date of the race\n* The time of the race\n* the end position of the jockey that you want to analyse \n\n> **Output;** **all parts are described in different part of the race separately (see track division part to understand it better)**\n\n* Some of the jockey's statistical information from the data set.\n* Some information about the jockey's competitors in the race and the comparison of their performance.\n* The jockey's performance is compared by other jockeys with the same end position as him in other horse racing.\n* It provides some graphs to describe the game\n* By analysing all information it decides if the end position of the jockey is the expected end position or not.","metadata":{}},{"cell_type":"code","source":"all_Jockeys_data=pd.read_csv('../input/all-jockeys-datacsv/all_Jockeys_data.csv')\nall_Jockeys_data['program_id']=all_Jockeys_data['program_id'].astype(str)\nall_Jockeys_data=all_Jockeys_data.drop('Unnamed: 0',axis=1)\nfor k in all_Jockeys_data.columns[:7]:\n    for i in range(len(all_Jockeys_data)):\n        all_Jockeys_data[k].values[i]=all_Jockeys_data[k].values[i].replace(\"[\",\"\").replace(\"]\",\"\").replace(\"\\'\",\"\").split(',')\nfor k in all_Jockeys_data.columns[:7]:\n    for i in range(len(all_Jockeys_data)):\n        for j in range(1,8):\n            all_Jockeys_data[k].values[i][j]=float(all_Jockeys_data[k].values[i][j])\nFPP=pd.read_csv('../input/fps-data1/FP.csv')\ndef main_Algorithm(data,all_Jockeys_data,race,date,time,jockey_position):\n    game_wrong=''\n    for i in range(len(FPP)):\n        if FPP['0'].values[i]==race and FPP['1'].values[i]==date and FPP['2'].values[i]==time:\n            print(\"Unfortuantly this horse racing can not be analyzed. It seems the given latitudes and longitudes coordinates are not accurate. Please select another race and try again.   \")\n            game_wrong='yes'\n            break\n    if game_wrong!='yes':\n        L,pass_game,kkk=prepare_data_of_a_game(data,race,date,time)\n        f,positions=find_point(L,race)\n        game_info,race_shapeN,race_shape,starting_points,end_points,race_parts,indS=finding_corners_interval(L,race,positions)\n        #race_parts=['First_Straight_Way','First_Corner','Second_Corner','Second_Straight_Way','Third_Corner','Forth_Corner','Third_Straight_Way']\n        jockey_game=data[(data[0]==race)&(data[1]==date)&(data[13]==time)]\n        jockey_data=jockey_game[jockey_game[17]==jockey_position]\n        if str(jockey_data[3].values[0]).strip()=='1A' or str(jockey_data[3].values[0]).strip()=='1X':\n            jockey_data[3].values[0]='1'\n        if str(jockey_data[3].values[0]).strip()=='2B' or str(jockey_data[3].values[0]).strip()=='3X':\n            jockey_data[3].values[0]='2'\n\n        for j in range(len(L)):\n            game_info[j].append(str(0))\n            game_info[j].append(str(jockey_data[3].values[0]).strip())\n            game_info[j].append(jockey_data[8].values[0].strip())\n            game_info[j].append(jockey_data[9].values[0].strip())\n            game_info[j].append(jockey_data[11].values[0].strip())\n            game_info[j].append([race,date,time])\n        game_result=pd.DataFrame(game_info)\n        for i in range(len(L)):\n            L[i]=L[i][:indS]\n        game_result.columns=['First_Straight_Way','First_Corner','Second_Corner','Second_Straight_Way','Third_Corner','Forth_Corner','Third_Straight_Way','index_id','program_id','course_type','track_condition','race_type','race_info']\n        program_id=game_result['program_id'].values[0]\n        race_type=game_result['race_type'].values[0]\n        track_condition=game_result['track_condition'].values[0]\n        course_type=game_result['course_type'].values[0]\n        end_pos=jockey_position-1\n        if race_shapeN!=2:\n            start=0\n        if race_shapeN==2:\n            start=3\n        all_stat=[]\n        sub_speed=[]\n        sub_LDB=[]\n        sub_LDF=[]\n        sub_SDF=[]\n        sub_SDB=[]\n        jockey_name=jockey_data[15].values[0]\n        #r,LDF,SDF,LDB,SDB,speed,positions_min,positions_max\n        jockey_statistic=data[data[15]==jockey_data[15].values[0]].drop_duplicates([0,1,13])\n        jockey_statistic_index=list(jockey_statistic[17].value_counts().sort_index().index)\n        jockey_statistic_count=jockey_statistic[17].value_counts().sort_index().tolist()\n        speed1=game_result.iloc[:,start:race_shapeN].stack().str[5].fillna(0)\n        position_min=game_result.iloc[:,start:race_shapeN].stack().str[6][end_pos].fillna(0)\n        position_max=game_result.iloc[:,start:race_shapeN].stack().str[7][end_pos].fillna(0)\n        jockey_LDF=game_result.iloc[:,start:race_shapeN].stack().str[1][end_pos].fillna(0)\n        jockey_LDB=game_result.iloc[:,start:race_shapeN].stack().str[3][end_pos].fillna(0)\n        jockey_SDB=game_result.iloc[:,start:race_shapeN].stack().str[4][end_pos].fillna(0)\n        jockey_SDF=game_result.iloc[:,start:race_shapeN].stack().str[2][end_pos].fillna(0)\n        if race_shapeN==4:\n            all_Jockeys_data=all_Jockeys_data[(all_Jockeys_data['Third_Corner'].str[5].isna())]\n        if race_shapeN==7:\n            all_Jockeys_data=all_Jockeys_data[~(all_Jockeys_data['Third_Corner'].str[5].isna())]\n\n        same_end=all_Jockeys_data[(all_Jockeys_data['end_pos']==jockey_position)]\n        same_end_program_id=all_Jockeys_data[(all_Jockeys_data['end_pos']==jockey_position)&(all_Jockeys_data['program_id']==program_id)]\n        same_end_race_type=all_Jockeys_data[(all_Jockeys_data['end_pos']==jockey_position)&(all_Jockeys_data['race_type']==race_type)]\n        same_end_track_condition=all_Jockeys_data[(all_Jockeys_data['end_pos']==jockey_position)&(all_Jockeys_data['track_condition']==track_condition.strip())]\n        same_end_course_type=all_Jockeys_data[(all_Jockeys_data['end_pos']==jockey_position)& (all_Jockeys_data['course_type']==course_type)]\n        same_end_all=all_Jockeys_data[(all_Jockeys_data['end_pos']==jockey_position)&(all_Jockeys_data['course_type']==course_type)&(all_Jockeys_data['track_condition']==track_condition)&(all_Jockeys_data['race_type']==race_type)&(all_Jockeys_data['program_id']==program_id)]\n        #all_Jockeys_data=all_Jockeys_data.drop('end_pos',axis=1)\n        AS_same_end=same_end.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).mean().fillna(0)\n        AS_same_end_program_id=same_end_program_id.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).mean()[list(speed1[end_pos].index)].fillna(0)\n        AS_same_end_race_type=same_end_race_type.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).mean()[list(speed1[end_pos].index)].fillna(0)\n        AS_same_end_track_condition=same_end_track_condition.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).mean()[list(speed1[end_pos].index)].fillna(0)\n        AS_same_end_course_type=same_end_course_type.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).mean()[list(speed1[end_pos].index)].fillna(0)\n        AS_same_end_all=same_end_all.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).mean()[list(speed1[end_pos].index)].fillna(0)\n\n        LDF_same_end=same_end.iloc[:,start:race_shapeN].stack().str[1].groupby(level=1).mean().fillna(0)\n        LDF_same_end_program_id=same_end_program_id.iloc[:,start:race_shapeN].stack().str[1].groupby(level=1).mean().fillna(0)\n        LDF_same_end_race_type=same_end_race_type.iloc[:,start:race_shapeN].stack().str[1].groupby(level=1).mean().fillna(0)\n        LDF_same_end_track_condition=same_end_track_condition.iloc[:,start:race_shapeN].stack().str[1].groupby(level=1).mean().fillna(0)\n        LDF_same_end_course_type=same_end_course_type.iloc[:,start:race_shapeN].stack().str[1].groupby(level=1).mean().fillna(0)\n        LDF_same_end_all=same_end_all.iloc[:,start:race_shapeN].stack().str[1].groupby(level=1).mean().fillna(0)\n\n        LDB_same_end=same_end.iloc[:,start:race_shapeN].stack().str[3].groupby(level=1).mean().fillna(0)\n        LDB_same_end_program_id=same_end_program_id.iloc[:,start:race_shapeN].stack().str[3].groupby(level=1).mean().fillna(0)\n        LDB_same_end_race_type=same_end_race_type.iloc[:,start:race_shapeN].stack().str[3].groupby(level=1).mean().fillna(0)\n        LDB_same_end_track_condition=same_end_track_condition.iloc[:,start:race_shapeN].stack().str[3].groupby(level=1).mean().fillna(0)\n        LDB_same_end_course_type=same_end_course_type.iloc[:,start:race_shapeN].stack().str[3].groupby(level=1).mean().fillna(0)\n        LDB_same_end_all=same_end_all.iloc[:,start:race_shapeN].stack().str[3].groupby(level=1).mean().fillna(0)\n\n        SDF_same_end=same_end.iloc[:,start:race_shapeN].stack().str[2].groupby(level=1).mean().fillna(0)\n        SDF_same_end_program_id=same_end_program_id.iloc[:,start:race_shapeN].stack().str[2].groupby(level=1).mean().fillna(0)\n        SDF_same_end_race_type=same_end_race_type.iloc[:,start:race_shapeN].stack().str[2].groupby(level=1).mean().fillna(0)\n        SDF_same_end_track_condition=same_end_track_condition.iloc[:,start:race_shapeN].stack().str[2].groupby(level=1).mean().fillna(0)\n        SDF_same_end_course_type=same_end_course_type.iloc[:,start:race_shapeN].stack().str[2].groupby(level=1).mean().fillna(0)\n        SDF_same_end_all=same_end_all.iloc[:,start:race_shapeN].stack().str[2].groupby(level=1).mean().fillna(0)\n\n        SDB_same_end=same_end.iloc[:,start:race_shapeN].stack().str[4].groupby(level=1).mean().fillna(0)\n        SDB_same_end_program_id=same_end_program_id.iloc[:,start:race_shapeN].stack().str[4].groupby(level=1).mean().fillna(0)\n        SDB_same_end_race_type=same_end_race_type.iloc[:,start:race_shapeN].stack().str[4].groupby(level=1).mean().fillna(0)\n        SDB_same_end_track_condition=same_end_track_condition.iloc[:,start:race_shapeN].stack().str[4].groupby(level=1).mean().fillna(0)\n        SDB_same_end_course_type=same_end_course_type.iloc[:,start:race_shapeN].stack().str[4].groupby(level=1).mean().fillna(0)\n        SDB_same_end_all=same_end_all.iloc[:,start:race_shapeN].stack().str[4].groupby(level=1).mean().fillna(0)\n        good_jockey=[]\n        print(Fore.BLUE +'\\033[1m'+ 'About The jockey And His Statistical Records In The Data Set: ' +'\\033[0m' +'\\n')\n\n        print(f\"The name of the selected jockey is \" +'\\033[1m'+Fore.RED + f\"{jockey_data[15].values[0]}\" + '\\033[0m' + f\" and his program_id in this race is \" +'\\033[1m'+Fore.RED + f\"{jockey_data[3].values[0].strip()}\" + '\\033[0m' + f\". Some other race conditions are as follow: race_type=\" +'\\033[1m'+Fore.RED + f\" {jockey_data[8].values[0]}\" + '\\033[0m' + f\",track_condition=\" +'\\033[1m'+Fore.RED + f\" {jockey_data[9].values[0]}\" + '\\033[0m' + f\" and course_type=\" +'\\033[1m'+Fore.RED + f\" {jockey_data[11].values[0]}\" + '\\033[0m' +'. Also according to the given track ids, the race has a ' +'\\033[1m'+Fore.RED + f\"{race_shape}\" + '\\033[0m' + ' shape.\\n')\n        print(f\"He has participated in \" +'\\033[1m'+Fore.RED + f\" {jockey_statistic.shape[0]}\" + '\\033[0m' + f\" horse racing in this data set. His perfomance is as follows:\"+\"\\n\")\n        maxn=0\n        maxi=-1\n        best=''\n        for i,j in zip(jockey_statistic_index,jockey_statistic_count): \n            print(f\"In \" +'\\033[1m'+Fore.RED + f\" {j}\" + '\\033[0m' + f\" horse racings he had the \" +'\\033[1m'+Fore.RED + f\" {i}-th\" + '\\033[0m' + f\" end position (\" +'\\033[1m'+Fore.RED + f\" {j*100/jockey_statistic.shape[0]:.1f}\" + '\\033[0m' + f\"%). In \" +'\\033[1m'+Fore.RED + f\"{jockey_statistic[(jockey_statistic[17]==i)&(jockey_statistic[3]==program_id)].shape[0]}\" + '\\033[0m' + f\" of them he started with the same program_id, in \" +'\\033[1m'+Fore.RED + f\"{jockey_statistic[(jockey_statistic[17]==i)&(jockey_statistic[11]==race_type)].shape[0]}\" + '\\033[0m' + f\" of them race_type was the same, in \" +'\\033[1m'+Fore.RED + f\" {jockey_statistic[(jockey_statistic[17]==i)&(jockey_statistic[9]==track_condition)].shape[0]}\" + '\\033[0m' + f\" of them track_condition was the same, in \" +'\\033[1m'+Fore.RED + f\" {jockey_statistic[(jockey_statistic[17]==i)&(jockey_statistic[8]==course_type)].shape[0]}\" + '\\033[0m' + f\"  of them course_type was the same and in \" +'\\033[1m'+Fore.RED + f\" {jockey_statistic[(jockey_statistic[17]==i)&(jockey_statistic[3]==program_id)&(jockey_statistic[11]==race_type)&(jockey_statistic[9]==track_condition)&(jockey_statistic[8]==course_type)].shape[0]} \" + '\\033[0m' + f\" of them the situation of the game was exactly the same. \\n\")\n            if maxn<j:\n                maxn=j\n                maxi=i\n            if j*100/jockey_statistic.shape[0]>=50 and i==1:\n                    best='yes'\n                    print('He is a very successful jockey since in more than 50% of times he won the race!')\n        print(f'\\033[1m'+Fore.BLACK + f\"Point 1:\" + '\\033[0m' +f\"In the most races (\" +'\\033[1m'+Fore.RED + f\"{maxn} of them\" + '\\033[0m' + f\") his end position was \" +'\\033[1m'+Fore.RED + f\" {maxi}\" + '\\033[0m' + f\"\")\n        if maxn> jockey_statistic_count[0]+jockey_statistic_count[1]:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point 2:\" + '\\033[0m' +f\"Furthermore, he wasn't in top three end positions in the most of the times.\")\n\n        if maxn< jockey_statistic_count[0]+jockey_statistic_count[1]:    \n            print(f'\\033[1m'+Fore.BLACK + f\"Point 2:\" + '\\033[0m' +f\"he was in top two end positions in the most of the times.\")\n\n            if maxn== jockey_statistic_count[0] and best!='yes':\n\n                print(f'\\033[1m'+Fore.BLACK + f\"Point 2:\" + '\\033[0m' +f\"Actually, his performance is amazing since he was mostly in the first position (winner). \")\n                good_jockey='yea'\n        print(Fore.BLUE +'\\033[1m'+ '\\n About His Position During The Race With Respect Of Other Jockeys: ' +'\\033[0m' +'\\n')\n        print(f\"There were \" +'\\033[1m'+Fore.RED + f\"{jockey_game.drop_duplicates([15]).shape[0]}\" + '\\033[0m' + f\" jockies in this competition. The jockey's situations in different parts of the track are as below:\"+'\\n')\n        for q,p in zip(race_parts,range(race_shapeN)):\n            a=1\n            print(f\"In the \" +'\\033[1m'+Fore.BLUE + f\" {q}\" + '\\033[0m' + f\" His best position was the \" +'\\033[1m'+Fore.GREEN + f\" {position_min[q]+1}-th\" + '\\033[0m' + f\", and his worst position was the \" +'\\033[1m'+Fore.RED + f\" {position_max[q]+1}-th\" + '\\033[0m' + f\". The average speed of him in this part of the race was \" +'\\033[1m'+Fore.BLUE + f\" {speed1[end_pos][q]:.5f}\" + '\\033[0m' + f\" where the  \" +'\\033[1m'+Fore.GREEN + f\" {game_result.iloc[:,start:race_shapeN].apply(imax)[q]+1}-th\" + '\\033[0m' + f\" jockey had the largest average speed \" +'\\033[1m'+Fore.GREEN + f\" {game_result.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).max()[q]:.5f}\" + '\\033[0m' + f\", and \" +'\\033[1m'+Fore.RED + f\" {game_result.iloc[:,start:race_shapeN].apply(imin)[q]+1}-th\" + '\\033[0m' + f\" jockey had the lowest  \" +'\\033[1m'+Fore.RED + f\" {game_result.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).min()[q]:.5f}\" + '\\033[0m' + f\" . \")\n            if position_min[q]+1==position_max[q]+1:\n                print(f'\\033[1m'+Fore.BLACK + f\"Point {a}:\" + '\\033[0m' + f\"  His position didn't changed in this part of the race.\")\n                a=a+1\n            if speed1[end_pos][q]==game_result.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).min()[q]:\n                print(f'\\033[1m'+Fore.BLACK + f\"Point {a}:\" + '\\033[0m' + f\" He had the lowest speed in this part.\")\n                a=a+1\n            if speed1[end_pos][q]==game_result.iloc[:,start:race_shapeN].stack().str[5].groupby(level=1).max()[q]:\n                print(f'\\033[1m'+Fore.BLACK + f\"Point {a}:\" + '\\033[0m' + f\" He had the highest speed in this part.\")\n            print('\\n')\n\n\n        print(Fore.BLUE +'\\033[1m'+ '\\n About His Speed and Distances During The Race With Respect Of All Other Jockeys In The Data Set With The Same End Position In The Same Track Shape: ' +'\\033[0m' +'\\n')\n\n        print(f\"The average speeds of this jockey in different parts of the track are as follow:\\n \\n\" +'\\033[1m'+Fore.BLACK + f\"{speed1[end_pos]}\" + '\\033[0m' )\n\n        print(f\"\\n In the following, his average speed whith all other jockeys with the same end position has been compared. The speeds have been printed in the same order as above parts (Note that a negative percentage means that his speed was lower than the average speed of jockeys with the same end position):\"+'\\n')\n\n        all_zero=''\n        s=1\n        conditions=['','and with the same program_id','and with the same race_type','and with the same track_condition','and with the same course_type', 'and with the same race conditions (all above)']\n        AS_of_jockeys=[abs(AS_same_end[list(speed1[end_pos].index)]),abs(AS_same_end_program_id[list(speed1[end_pos].index)]),abs(AS_same_end_race_type[list(speed1[end_pos].index)]),abs(AS_same_end_track_condition[list(speed1[end_pos].index)]),abs(AS_same_end_course_type[list(speed1[end_pos].index)]),abs(AS_same_end_all[list(speed1[end_pos].index)])]\n        for q,k in zip(conditions,AS_of_jockeys):\n                hh=[round((j-i)*100/i,2) for j,i in zip(abs(speed1[end_pos]).round(5),k.round(5)) if i!=0]\n                sub_speed.append(hh)\n                print(f\"The average speed of jockeys with the \" +'\\033[1m'+Fore.BLACK + f\" {jockey_position}\" + '\\033[0m' + f\" -th end position \" +'\\033[1m'+Fore.BLACK + f\"{q}\" + '\\033[0m' + f\":\\n \" +'\\033[1m'+Fore.RED + f\" {list(k.round(5))}\" + '\\033[0m' + f\" (Percentages:  \" +'\\033[1m'+Fore.BLUE + f\" {[str(round((j-i)*100/i,2))+'%' for j,i in zip(abs(speed1[end_pos]).round(5),k.round(5)) if i!=0]} \" + '\\033[0m' + f\") \\n\")\n                if sum(n==0 for n in hh)==len(hh):\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As data shows this is the only race in the data set that has exactly the same conditions as the given race. That's why the last percentages are zero. \\n \")\n                    s=s+1\n                    all_zero='yeas'\n                min_ind=np.array(hh).argmax()\n                if all_zero!='yeas' and hh[min_ind]>0:\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As the persentages shows, in this case,\" +'\\033[1m'+Fore.GREEN + f\" {jockey_name}\" + '\\033[0m' + f\"  has a higher speed in\" +'\\033[1m'+Fore.GREEN + f\" {list(speed1[end_pos].index)[min_ind]}\" + '\\033[0m' + f\" in compare with the average rate.\\n\")\n                    s=s+1\n                if len(hh)>=2:\n                    sec_min=np.array(hh).argsort()[1]\n                    if hh[sec_min]>10 and all_zero!='yeas':\n                        print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" Also in the \" +'\\033[1m'+Fore.GREEN + f\"{list(speed1[end_pos].index)[sec_min]}\" + '\\033[0m' + f\" his performance is better than the average rate more than 10%. \\n\")\n                        s=s+1\n        all_stat.append(sub_speed)    \n        LDFl=[]\n        print(f\"The longest distance of this jockey with jockies in front of him in different parts of the track are as follow:\\n \\n\" +'\\033[1m'+Fore.BLACK + f\"{abs(jockey_LDB)}\" + '\\033[0m' )\n        all_zero=''\n        print(f\"\\n In the following, these distances are compared with the average of the longest distance of all other jockeys (with the same end position {jockey_position}-th) with their further competitors. Distances have been printed in the same order as above parts (Note that a negative percentage means that his distance with further jockeys is shorter which shows that he is doing a good job in those parts. The -100% simply means there is no jockey in front of {jockey_name} in that part of the race.\"+'\\n')\n        s=1\n        lost_in_last_part=''\n        conditions=['','and with the same program_id','and with the same race_type','and with the same track_condition','and with the same course_type', 'and with the same race conditions (all above)']\n        LDB_of_jockeys=[abs(LDB_same_end[list(jockey_LDB.index)]),abs(LDB_same_end_program_id[list(jockey_LDB.index)]),abs(LDB_same_end_race_type[list(jockey_LDB.index)]),abs(LDB_same_end_track_condition[list(jockey_LDB.index)]),abs(LDB_same_end_course_type[list(jockey_LDB.index)]),abs(LDB_same_end_all[list(jockey_LDB.index)])]\n        for q,k in zip(conditions,LDB_of_jockeys):\n                hh=[round((j-i)*100/i,2) for j,i in zip(abs(jockey_LDB).round(5),k.round(5)) if i!=0]\n                if q=='':\n                    LDFl.append(hh)\n                sub_LDB.append(hh)\n                print(f\"The average of the largest distance of jockeys with the \" +'\\033[1m'+Fore.BLACK + f\" {jockey_position}\" + '\\033[0m' + f\" -th end position \" +'\\033[1m'+Fore.BLACK + f\"{q}\" + '\\033[0m' + f\":\\n \" +'\\033[1m'+Fore.RED + f\" {list(k.round(5))}\" + '\\033[0m' + f\" (Percentages:  \" +'\\033[1m'+Fore.BLUE + f\" {[str(round((j-i)*100/i,2))+'%' for j,i in zip(abs(jockey_LDB).round(5),k.round(5)) if i!=0]} \" + '\\033[0m' + f\") \\n\")\n                if sum(n==0 for n in hh)==len(hh):\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As data shows this is the only race in the data set that has exactly the same conditions as the given race. That's why the last percentages are zero. \\n \")\n                    s=s+1\n                    all_zero='yeas'\n                min_ind=np.array(hh).argmin()\n                if all_zero!='yeas' and hh[min_ind]<0:\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As the persentages shows, in this case,\" +'\\033[1m'+Fore.GREEN + f\" {jockey_name}\" + '\\033[0m' + f\"  did a good job in the \" +'\\033[1m'+Fore.GREEN + f\" {list(jockey_LDB.index)[min_ind]}\" + '\\033[0m' + f\"  part of the track in compare with the average rate.\\n\")\n                    s=s+1\n                if len(hh)>=2:\n                    sec_min=np.array(hh).argsort()[1]\n                    if hh[sec_min]<-50 and all_zero!='yeas':\n                        print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" Also in the \" +'\\033[1m'+Fore.GREEN + f\"{list(jockey_LDB.index)[sec_min]}\" + '\\033[0m' + f\" his is closer to his competitors more than two times better than the average rate. \\n\")\n                        s=s+1\n                if sum(n<0 for n in hh)==len(hh):\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" The negatives persentages shows that his distance with his front competitors is less then the average distance rate in all parts of the race! GREET JOB \" +'\\033[1m'+Fore.GREEN + f\"{jockey_name}\" + '\\033[0m'+ \"\\n\")\n                    s=s+1\n                if len(hh)==4:\n                    if sum(n<0 for n in hh)==len(hh)-1 and hh[3]>0 :\n                        print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" The negatives persentages shows that his distance with his front competitors is less then the average distance rate in the three first parts of the race! But in the last part his distance with his front competitors increased in compare to the average rate! \\n\")\n                        s=s+1\n                        lost_in_last_part='yes'\n                        if hh[3]>80:\n                            print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" Woow! in the \" +'\\033[1m'+Fore.GREEN + f\"{list(jockey_LDB.index)[len(hh)-1]}\" + '\\033[0m' + f\" part he kind of lost the game. His distance with the front competitors increased significantly!race! \\n\")\n                            s=s+1\n        all_stat.append(sub_LDB)            \n\n        LDBl=[]\n        print(f\"The longest distance of this jockey with jockies behind him in different parts of the track are as follow:\\n \\n\" +'\\033[1m'+Fore.BLACK + f\"{abs(jockey_LDF)}\" + '\\033[0m' )\n        all_zero=''\n        print(f\"\\n In the following, these distances are compared with the longest distance of all other jockeys (with the same end position {jockey_position}-th) with their behind competitors. Distances have been printed in the same order as above parts (Note that a negative percentage means that his distance with behind jockeys is shorter. The -100% simply means he is behind of all other jockeyes in that part of the race.\"+'\\n')\n        s=1\n        conditions=['','and with the same program_id','and with the same race_type','and with the same track_condition','and with the same course_type', 'and with the same race conditions (all above)']\n        LDF_of_jockeys=[abs(LDF_same_end[list(jockey_LDF.index)]),abs(LDF_same_end_program_id[list(jockey_LDF.index)]),abs(LDF_same_end_race_type[list(jockey_LDF.index)]),abs(LDF_same_end_track_condition[list(jockey_LDF.index)]),abs(LDF_same_end_course_type[list(jockey_LDF.index)]),abs(LDF_same_end_all[list(jockey_LDF.index)])]\n        for q,k in zip(conditions,LDF_of_jockeys):\n                hh=[round((j-i)*100/i,2) for j,i in zip(abs(jockey_LDF).round(5),k.round(5)) if i!=0]\n\n                if q=='':\n                    LDBl.append(hh)\n                sub_LDF.append(hh)\n                print(f\"The average of the largest distance of jockeys with the \" +'\\033[1m'+Fore.BLACK + f\" {jockey_position}\" + '\\033[0m' + f\" -th end position \" +'\\033[1m'+Fore.BLACK + f\"{q}\" + '\\033[0m' + f\":\\n \" +'\\033[1m'+Fore.RED + f\" {list(k.round(5))}\" + '\\033[0m' + f\" (Percentages:  \" +'\\033[1m'+Fore.BLUE + f\" {[str(round((j-i)*100/i,2))+'%' for j,i in zip(abs(jockey_LDF).round(5),k.round(5)) if i!=0]} \" + '\\033[0m' + f\") \\n\")\n                if sum(n==0 for n in hh)==len(hh):\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As data shows this is the only race in the data set that has exactly the same conditions as the given race. That's why the last percentages are zero. \\n \")\n                    s=s+1\n                    all_zero='yeas'\n                min_ind=np.array(hh).argmax()\n                if all_zero!='yeas' and hh[min_ind]>0:\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As the persentages shows, in this case,\" +'\\033[1m'+Fore.GREEN + f\" {jockey_name}\" + '\\033[0m' + f\"  did a good job in the \" +'\\033[1m'+Fore.GREEN + f\" {list(jockey_LDF.index)[min_ind]}\" + '\\033[0m' + f\"  part of the track in compare with the average rate.\\n\")\n                    s=s+1\n                if len(hh)==4:\n                    sec_min=np.array(hh).argsort()[-2]\n                    if hh[sec_min]>50 and all_zero!='yeas':\n                        print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" Also in the \" +'\\033[1m'+Fore.GREEN + f\"{list(jockey_LDF.index)[sec_min]}\" + '\\033[0m' + f\" his is closer to his competitors more than two times better than the average rate. \\n\")\n                        s=s+1\n\n                    if sum(n<0 for n in hh)==len(hh)-1 and hh[3]>0:\n                        print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" WOW!, His distance is lower than the average rate in the three first of the race, but in final part, he could increase his distance with other competitors more than the average rate. \\n\")\n        all_stat.append(sub_LDF)            \n        #jockey_SDF=jockey_SDF.fillna(0)\n        #SDF_same_end_all=SDF_same_end_all.fillna(0)\n        print(f\"The shortest distance of this jockey with jockies behind him in different part of the track are as follow:\\n \\n\" +'\\033[1m'+Fore.BLACK + f\"{abs(jockey_SDF)}\" + '\\033[0m' )\n        all_zero=''\n        SDBl=[]\n        print(f\"\\n In the following, these distances are compared with the shortest distance of all other jockeys (with the same end position {jockey_position}-th) with their behind competitors. Distances have been printed in the same order as above parts (Note that a negative percentage means that his distance with behind jockeys is shorter. The -100% simply means he is behind of all other jockeyes in that part of the race.\"+'\\n')\n        s=1\n        conditions=['','and with the same program_id','and with the same race_type','and with the same track_condition','and with the same course_type', 'and with the same race conditions (all above)']\n        SDF_of_jockeys=[abs(SDF_same_end[list(jockey_SDF.index)]),abs(SDF_same_end_program_id[list(jockey_SDF.index)]),abs(SDF_same_end_race_type[list(jockey_SDF.index)]),abs(SDF_same_end_track_condition[list(jockey_SDF.index)]),abs(SDF_same_end_course_type[list(jockey_SDF.index)]),abs(SDF_same_end_all[list(jockey_SDF.index)])]\n        for q,k in zip(conditions,SDF_of_jockeys):\n                hh=[round((j-i)*100/i,2) for j,i in zip(abs(jockey_SDF).round(5),k.round(5)) if i!=0]\n                if q=='':\n                    SDBl.append(hh)\n                sub_SDF.append(hh)\n                print(f\"The average of the largest distance of jockeys with the \" +'\\033[1m'+Fore.BLACK + f\" {jockey_position}\" + '\\033[0m' + f\" -th end position \" +'\\033[1m'+Fore.BLACK + f\"{q}\" + '\\033[0m' + f\":\\n \" +'\\033[1m'+Fore.RED + f\" {list(k.round(5))}\" + '\\033[0m' + f\" (Percentages:  \" +'\\033[1m'+Fore.BLUE + f\" {[str(round((j-i)*100/i,2))+'%' for j,i in zip(abs(jockey_SDF).round(5),k.round(5)) if i!=0]} \" + '\\033[0m' + f\") \\n\")\n                if sum(n==0 for n in hh)==len(hh):\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As data shows this is the only race in the data set that has exactly the same conditions as the given race. That's why the last percentages are zero. \\n \")\n                    s=s+1\n                    all_zero='yeas'\n                min_ind=np.array(hh).argmax()\n                if all_zero!='yeas' and hh[min_ind]>0:\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As the persentages shows, in this case,\" +'\\033[1m'+Fore.GREEN + f\" {jockey_name}\" + '\\033[0m' + f\"  did a good job in the \" +'\\033[1m'+Fore.GREEN + f\" {list(jockey_SDF.index)[min_ind]}\" + '\\033[0m' + f\"  part of the track in compare with the average rate.\\n\")\n                    s=s+1\n                if len(hh)==4:\n                    sec_min=np.array(hh).argsort()[-2]\n                    if hh[sec_min]>50 and all_zero!='yeas':\n                        print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" Also in the \" +'\\033[1m'+Fore.GREEN + f\"{list(jockey_SDF.index)[sec_min]}\" + '\\033[0m' + f\" his is closer to his competitors more than two times better than the average rate. \\n\")\n                        s=s+1\n                if q=='and with the same program_id' and sum(n<0 for n in hh)==len(hh)-1 and hh[0]>0:\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\"As you can see with the same \" +'\\033[1m'+Fore.GREEN + f\"{'program_id'}\" + '\\033[0m' + f\" he had a better performance in the first part of the race in compare to the average rate. But not in other parts! \\n\")\n                    s=s+1\n        all_stat.append(sub_SDF)\n        print(f\"The longest distance of this jockey with jockies in front of him in different parts of the track are as follow:\\n \\n\" +'\\033[1m'+Fore.BLACK + f\"{abs(jockey_SDB)}\" + '\\033[0m' )\n        all_zero=''\n        print(f\"\\n In the following, these distances are compared with the average of longest distance of all other jockeys (with the same end position {jockey_position}-th) with their further competitors. Distances have been printed in the same order as above parts (Note that a negative percentage means that his distance with further jockeys is shorter which shows that he is doing a good job in those parts. The -100% simply means there is no jockey in front of {jockey_name} in that part of the race.\"+'\\n')\n        s=1\n        SDFl=[]\n        conditions=['','and with the same program_id','and with the same race_type','and with the same track_condition','and with the same course_type', 'and with the same race conditions (all above)']\n        SDB_of_jockeys=[abs(SDB_same_end[list(jockey_SDB.index)]),abs(SDB_same_end_program_id[list(jockey_SDB.index)]),abs(SDB_same_end_race_type[list(jockey_SDB.index)]),abs(SDB_same_end_track_condition[list(jockey_SDB.index)]),abs(SDB_same_end_course_type[list(jockey_SDB.index)]),abs(SDB_same_end_all[list(jockey_SDB.index)])]\n        for q,k in zip(conditions,SDB_of_jockeys):\n                hh=[round((j-i)*100/i,2) for j,i in zip(abs(jockey_SDB).round(5),k.round(5)) if i!=0]\n                if q=='':\n                    SDFl.append(hh)\n                sub_SDB.append(hh)\n                print(f\"The average of the largest distance of jockeys with the \" +'\\033[1m'+Fore.BLACK + f\" {jockey_position}\" + '\\033[0m' + f\" -th end position \" +'\\033[1m'+Fore.BLACK + f\"{q}\" + '\\033[0m' + f\":\\n \" +'\\033[1m'+Fore.RED + f\" {list(k.round(5))}\" + '\\033[0m' + f\" (Percentages:  \" +'\\033[1m'+Fore.BLUE + f\" {[str(round((j-i)*100/i,2))+'%' for j,i in zip(abs(jockey_SDB).round(5),k.round(5)) if i!=0]} \" + '\\033[0m' + f\") \\n\")\n                if sum(n==0 for n in hh)==len(hh):\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As data shows this is the only race in the data set that has exactly the same conditions as the given race. That's why the last percentages are zero. \")\n                    s=s+1\n                    all_zero='yeas'\n                min_ind=np.array(hh).argmin()\n                if all_zero!='yeas' and hh[min_ind]<0:\n                    print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" As the persentages shows, in this case,\" +'\\033[1m'+Fore.GREEN + f\" {jockey_name}\" + '\\033[0m' + f\"  did a good job in the \" +'\\033[1m'+Fore.GREEN + f\" {list(jockey_SDB.index)[min_ind]}\" + '\\033[0m' + f\"  part of the track in compare with the average rate.\\n\")\n                    s=s+1\n                if len(hh)>=2:\n                    sec_min=np.array(hh).argsort()[1]\n                    if hh[sec_min]<-50 and all_zero!='yeas':\n                        print(f'\\033[1m'+Fore.BLACK + f\"Point {s}:\" + '\\033[0m' + f\" Also in the \" +'\\033[1m'+Fore.GREEN + f\"{list(jockey_SDB.index)[sec_min]}\" + '\\033[0m' + f\"  part his is closer to his competitors two times better than the average rate. \\n\")\n                        s=s+1\n        p=0\n        all_stat.append(sub_SDB)    \n        dat=pd.DataFrame(all_stat)\n        indx1=dat[0:1].apply(imax0,axis=1)[0]\n        indx2=dat[0:1].apply(imin0,axis=1)[0]\n        indx3=dat[0:1].apply(imax0,axis=1)[0]\n        indx4=dat[0:1].apply(imax0,axis=1)[0]\n        indx5=dat[0:1].apply(imin0,axis=1)[0]\n        MyList=[indx1,indx2,indx3,indx4,indx5]\n        print(Fore.BLUE +'\\033[1m'+ ' \\n Conclusions: ' +'\\033[0m' +'\\n')\n        conditions=['','program_id','race_type','track_condition','course_type', 'same race conditions (all above)']\n        dic={i:MyList.count(i) for i in MyList}\n        effective_cond=sorted(dic.items(), key=lambda item: item[0])[0][0]\n        effective_count=sorted(dic.items(), key=lambda item: item[0])[0][1]\n        min_ind_LDB=np.array(pd.DataFrame(all_stat).iloc[2:4,:1].values[0][0]).argmin()\n        #print(min_ind_LDB,min(dat.iloc[2:4,:1].values[0].min()))\n\n\n        if effective_count>1 and effective_cond!=0:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\" It seems the jockey has a better performance in races with the same \" +'\\033[1m'+Fore.GREEN + f\"{conditions[effective_cond]}.\" + '\\033[0m' + f\"Furthermore, from the statistical point of view that can increase the perfermonace of him. \\n\")\n            p=p+1\n        if effective_count>1 and effective_cond==0:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\" It seems the jockey's performance is not co-related to the conditions that were mentioned during the analysis (such as program id, race type, ...). \\n\")\n            p=p+1\n            if good_jockey=='yes':\n                print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\" Actually, he is a very successful jockey in all conditions.  \\n\")\n                p=p+1\n        first_pos=''\n        if min(dat.iloc[2:4,:1].values[0].min())==-100:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' +f\"The jockey was the last one in the \" +'\\033[1m'+Fore.RED + f\" {race_parts[min_ind_LDB]}\" + '\\033[0m' + f\" of the track!\")\n            if jockey_position==1:\n                print(\"But he could finish the race with the first end position! wooooow \\n\")\n            p=p+1\n\n        if position_min.max()==0 and position_min.min()==0 and position_max.max()==0 and position_max.min()==0 : \n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\" This was an incredible performance! Exceeeeeellent! He was in the first position all the time during the race. \\n\")\n            p=p+1\n            first_pos='yes'\n        first_pos1=''\n        if position_min.max()==0 and position_min.max()==0 and first_pos!='yes': \n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\" This is definitely an expected end position for \" +'\\033[1m'+Fore.GREEN + f\"{jockey_name}.\" + '\\033[0m' + f\" Because his best position was the first in all \\033[1m\"+Fore.BLACK + f\"{race_shapeN} parts\" + '\\033[0m' + f\" of the track. \\n\")\n            p=p+1\n            first_pos1='yes'\n\n        if jockey_position -position_min.max()>3 and jockey_position -position_min[race_shapeN-1]>3:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\" This is not raelly an expected end position for the jockey. His position was better than his end position even in the \" +'\\033[1m'+Fore.GREEN + f\"{race_parts[race_shapeN-1]}.\" + '\\033[0m' + f\" + '\\033[0m', but in a very last seconds his speed dropped!  \\n\")\n            p=p+1\n            min_speed_index=[np.array(all_stat[0][j]).argmin() for j in range(len(all_stat[0]))]\n            if min(min_speed_index)==max(min_speed_index)==len(min_speed_index)-1:\n                print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\" But it should be mentioned that, his average speed in the last part of the shape (i.e. \" +'\\033[1m'+Fore.GREEN + f\"{race_parts[race_shapeN-1]}.\" + '\\033[0m' + f\" ) is less than the average speed which might be the reason why he lsot the game! Or didn't have a better end position. \\n\")\n                p=p+1\n\n        if lost_in_last_part=='yes' and jockey_position>3:\n                print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\" Except the last part of the track, he did a good job in all other parts. You can see in the above his distance with the front competitors was less than the avrage rate!!!! In other words his poor performance in the last part of the track is the reason of this end position. \\n\")\n                p=p+1\n\n\n        w=0    \n        for i in range(6):        \n            if min(all_stat[1][i])<= 0 and max(all_stat[1][i])<=0:\n                w=w+1\n        if w== 6 and jockey_position!=1:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\" He was very close to his competitors and had a good chance to finish the game with a better end position. \\n\")\n            p=p+1\n        diffp=position_max-position_min\n        great_j=''\n        great_job=diffp[diffp>4]\n        if great_job.shape[0]!=0:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"The jockey did a great job in  \" +'\\033[1m'+Fore.GREEN + f\"{list(great_job.index)}.\" + '\\033[0m' + f\", since he passed more than 4 jockeys in this/these part/parts. \\n\")\n            great_j='yes'\n        good_job=diffp[diffp>3]\n        if great_job.shape[0]==0 and good_job.shape[0]!=0 and great_j!='yes':\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"The jockey did a good job in  \" +'\\033[1m'+Fore.GREEN + f\"{list(good_job.index)}.\" + '\\033[0m' + f\", since he passed more than 3 jockeys in this/these part/parts. \\n\")\n\n        SDFN=sum(n<0 for n in SDFl[0])\n        SDFN1=sum(n<0 for n in SDFl[0][1:]) \n        SDFP=sum(n>0 for n in SDFl[0])\n        SDFP1=sum(n>0 for n in SDFl[0][1:])\n        LDFN=sum(n<0 for n in LDFl[0])\n        LDFN1=sum(n<0 for n in LDFl[0][1:]) \n        LDFP=sum(n>0 for n in LDFl[0])\n        LDFP1=sum(n>0 for n in LDFl[0][1:])\n\n        SDBN=sum(n<0 for n in SDBl[0])\n        SDBN1=sum(n<0 for n in SDBl[0][1:]) \n        SDBP=sum(n>0 for n in SDBl[0])\n        SDBP1=sum(n>0 for n in SDBl[0][1:])\n        LDBN=sum(n<0 for n in LDBl[0])\n        LDBN1=sum(n<0 for n in LDBl[0][1:]) \n        LDBP=sum(n>0 for n in LDBl[0])\n        LDBP1=sum(n>0 for n in LDBl[0][1:])\n        if LDFN==1 and LDFl[0][-1]<0:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"The jockey definitely could finish the race with a worth end position. He did a good job in the last part of the track and that's why he ended the race by this position!\\n\")\n            p=p+1\n        if race_shapeN==4:\n            if sum(n<0 for n in LDBl[0][:3])==3 and sum(n>=0 for n in LDBl[0][3:4])==1:\n                print(\"It should be mentioned that his position was so close to other compatitors in the three first parts of the track, but he could increase his distance with his behind compatitors in the last part of the race. This shows that how the performance of a jockey is important in the last part of the track!\\n \")\n        distance_BehindN=''\n        distance_BehindP=''\n        not_expect_better=''\n        not_expect_worth=''\n        distance_FurtherN=''\n        distance_FurtherP=''\n        contract=''\n        both_D=''\n        if SDFN==len(SDFl[0]) and LDFN==len(LDFl[0]) and SDBN==len(SDBl[0]) and LDBN==len(LDBl[0]) and jockey_position!=len(L):\n            contract='yes'\n            both_D='yes'\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'Since his distance with further jockeys was close during the race, he could finish the race with a better end position. But he also had very close distance with jockey/jockeys behind him! \\n')\n            p=p+1\n        if SDFN==len(SDFl[0]) and LDFN==len(LDFl[0]) and SDBN==len(SDBl[0]) and LDBN==len(LDBl[0]) and jockey_position==len(L):\n            contract='yes'\n            both_D='yes'\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'Since his distance with further jockeys was close during the race, he could finish the race with a better end position. But he lost the game because his distance was very close with his behind compatitors as well, and in the last part of the track every body passed from him. \\n ')\n            p=p+1\n        if SDFN==len(SDFl[0]) and LDFN==len(LDFl[0]) and SDBP==len(SDBl[0]) and LDBP==len(LDBl[0]) and jockey_position!=1:\n            not_expect_better='yes'\n            both_D='yes'\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This is not an expected end position. The jockey could definitely finish the race with a better end position since his performance was way better than average rate. he was very close to his further compatitors and had a enough space with jockeys behind him.\\n ')\n            p=p+1\n        if SDFN1==len(SDFl[0][1:]) and LDFN1==len(LDFl[0][1:]) and SDBP1==len(SDBl[0][1:]) and LDBP1==len(LDBl[0][1:]) and jockey_position!=1:\n            not_expect_better='yes'\n            both_D='yes'\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This is not an expected end position. Except the first part, (First_straight_way), The jockey could definitely finish the race with a better end position since his performance was way better than average rate. he was very close to his further compatitors and had a enough space with jockeys behind him.\\n ')\n            p=p+1\n        if SDFP==len(SDFl[0]) and LDFP==len(LDFl[0]) and SDBN==len(SDBl[0]) and LDBN==len(LDBl[0]) and jockey_position!=len(L):\n            not_expect_worth='yes'\n            #print(f\"yes {len(L)} and {jockey_position}\")\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This is not an expected end position. It was expected the jockey to finish the game with a worth end position. His game should be analyzed in more details to see how he finished with this end position. \\n')\n            p=p+1\n        if SDFP==len(SDFl[0]) and LDFP==len(LDFl[0]) and SDBN==len(SDBl[0]) and LDBN==len(LDBl[0]) and jockey_position==len(L):\n            not_expect_worth='yes'\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This is an expected position! the performance of the jockey was very poor in the race.\\n')\n            p=p+1\n\n        if SDFP1==len(SDFl[0][1:]) and LDFP1==len(LDFl[0][1:]) and SDBN1==len(SDBl[0][1:]) and LDBN1==len(LDBl[0][1:]) and jockey_position!=len(L):\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This is not an expected end position. It was expected the jockey to finish the game with a worth end position. His game should be analyzed in more details to see how he finished with this end position. \\n')\n            not_expect_worth='yes'\n            p=p+1\n\n        if SDFP1==len(SDFl[0][1:]) and LDFP1==len(LDFl[0][1:]) and SDBN1==len(SDBl[0][1:]) and LDBN1==len(LDBl[0][1:]) and jockey_position==len(L):\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This is an expected position! the performance of the jockey was very poor in the race.\\n')\n            not_expect_worth='yes'\n            p=p+1\n\n        if SDFN==len(SDFl[0]) and LDFN==len(LDFl[0]) and not_expect_better!='yes' and jockey_position!=1 and contract!='yes':\n            distance_FurtherN='yes'\n            both_D='yes'\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'The distance of the jockey with his further compatitors is less than the avrage rate. So he could pass his further compatitor for a better end position.\\n')\n            p=p+1\n        if distance_FurtherN!='yes' and SDFN1==len(SDFl[0][1:]) and LDFN1==len(LDFl[0][1:]) and contract!='yes' and not_expect_better!='yes' and jockey_position!=1:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'Except the first part of the race (First_straight_way), the distance of the jockey with his further compatitors is less than the avrage rate. So he could pass his further compatitor for a better end position.\\n')\n            p=p+1\n        if SDBN==len(SDBl[0]) and LDBN==len(LDBl[0]) and not_expect_worth!='yes' and contract!='yes' and distance_FurtherN!='yes':\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'The distance of the jockey with his behind compatitor is less than average. In other words, other jockeys could overtake his position .\\n')\n            p=p+1\n            if first_pos1=='yes':\n                print('Indeed, however his best position was the first in all part of the race, he could be passed by other jockeys because his distance was so close to other compatitors!  \\n ')\n            distance_BehindN='yes'\n        if distance_BehindN!='yes' and SDBN==len(SDBl[0]) and LDBN==len(LDBl[0]) and contract!='yes' and not_expect_worth!='yes':\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'Except the first part of the race (First_straight_way), the distance of the jockey with his behind compatitor is less than average.  In other words, other jockeys could overtake his position \\n.')\n            p=p+1\n            distance_BehindN='yes'\n\n\n        if SDFP==len(SDFl[0]) and LDFP==len(LDFl[0]) and not_expect_worth!='yes' and distance_BehindN!='yes' and jockey_position!=1:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f' The distance of the jockey with his further compatitor is more than average. So the chance of him to pass further jockeys was low during the game.\\n')\n            distance_FurtherP='yes'\n            p=p+1\n        if SDFP1==len(SDFl[0][1:]) and LDFP1==len(LDFl[0][1:]) and not_expect_worth!='yes' and distance_FurtherP!='yes':\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'Except the first part of the race (First_straight_way), the distance of the jockey with his further compatitor is more than average.\\n ')\n            p=p+1\n            if first_pos1=='yes':\n                print('Indeed, however his best position was the first in all part of the race, he could be passed by other jockeys because his distance was so close to other compatitors!  \\n ')\n            else:\n                print('He could finish the race with a worth end position.\\n')\n\n        #if SDBP==len(SDBl[0]) and LDBP==len(LDBl[0]) and not_expect_better!='yes':\n            #print('The distance of the jockey with his behind compatitors is more than average. He could finish the race with a better end position.')\n            #distance_BehindP='yes'\n        #if SDBP1==len(SDBl[0][1:]) and LDBP1==len(LDBl[0][1:]) and not_expect_better!='yes' and distance_BehindP!='yes':\n            #print('Except the first part of the race (First_straight_way), the distance of the jockey with his behind compatitors is more than average. He could finish the race with a better end position.')\n        if LDFN==len(LDFl[0]) and both_D!='yes':\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"The distance of the jockey with further compatitors was less than average in all part of the track. \\n\")\n            p=p+1\n        first_could=''\n        if jockey_position!=1 and LDFl[0][-1]==-100:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This jockey definitely could be in the first position.\\n')\n            p=p+1\n            first_could='yes'\n        if jockey_position!=1 and SDFl[0][-1]==-100 and first_could!='yes':\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This jockey definitely could be in the first position.\\n')\n            p=p+1\n\n        if jockey_position==1 and LDFl[0][-1]!=-100:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This jockey was kind of lucky to win the race. His position was very close to his compatitors even in the final part of the race.\\n')\n            first_could='yes'\n            p=p+1\n        if jockey_position==1 and SDFl[0][-1]!=-100 and first_could!='yes':\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'This jockey was kind of lucky to win the race. His position was very close to his compatitors even in the final part of the race.\\n')        \n            p=p+1\n        if min(position_min.tolist())>=jockey_position and jockey_position!=1:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f'His end position could be worth, because this end position was his best position during the race \\n')\n            p=p+1\n        last_better=''\n        diffp=position_max-position_min\n        position_minr=position_min.reset_index()\n        position_maxr=position_max.reset_index()\n        equal=diffp[diffp==0]\n        equal_data=position_max.loc[list(equal.index)]\n        if equal.shape[0]!=0:\n            equal_data=equal_data+1\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"The jockey's position never chanched in the following parts (the number in front of each part is the jockey's position):\\n \\n\" +'\\033[1m'+Fore.GREEN + f\"{equal_data}.\" + \". \\n \\n\")\n            p=p+1\n            if equal_data[equal_data==jockey_position].shape[0]!=0:\n                print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"As you can see, he was in his end position in all part of \" +'\\033[1m'+Fore.GREEN + f\"{list(equal_data[equal_data==jockey_position].index)}.\" + '\\033[0m' )\n                p=p+1\n                #print(list(equal_data.index)[-1],race_parts[-1])\n            if equal_data[equal_data==len(L)].shape[0]!=0 and jockey_position!=len(L):\n                print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"As you can see, he was in the last  position in all part of \" +'\\033[1m'+Fore.GREEN + f\"{list(equal_data[equal_data==len(L)].index)}.\" + '\\033[0m' + f\" . But he could finish the race with a better position!\")\n                p=p+1\n                if jockey_position==1:\n                    print(\"Well, surprising he won the race!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\")\n                if list(equal_data.index)[-1]==race_parts[:race_shapeN][-1]:\n                    print(f\"He was in this position in all part of \" +'\\033[1m'+Fore.GREEN + f\"{race_parts[:race_shapeN][-1]}.\" + '\\033[0m' + f'. Regardless his performance in other part of the race, he could keep himself in his position in this part! which is the most important part of the race!')\n\n            if equal_data[equal_data==1].shape[0]!=0 and jockey_position!=1:\n                print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"As you can see, he was in the first  position in all part of \" +'\\033[1m'+Fore.GREEN + f\"{list(equal_data[equal_data==1].index)}.\" + '\\033[0m' + f\". But he could not keep him self in this position!\")\n                p=p+1\n                if jockey_position>3:\n                    print(f\"it is surprising why he ended up with this end position when he was in the first position in all part of \" +'\\033[1m'+Fore.GREEN + f\"{list(equal_data[equal_data==1].index)}.\" + '\\033[0m' )\n\n        if position_min.min()==0:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"He was in the first position in some track_ids in \" +'\\033[1m'+Fore.GREEN + f\"{list(position_min[position_min==0].index)}.\" + '\\033[0m'+\" part/parts of the track.\")\n            p=p+1\n            if position_max.max()==len(L)-1:\n                first_position_i=list(position_minr[position_minr[0]==0].index)[-1]\n                last_position_i=list(position_maxr[position_maxr[0]==(len(L)-1)].index)[-1]\n                if last_position_i<first_position_i:\n                    if jockey_position<=3 and jockey_position!=1:\n                        last_better='yes'\n                        print(f\"However, he was the last jockey in some part of \" +'\\033[1m'+Fore.GREEN + f\"{list(position_max[position_max==(len(L)-1)].index)}.\" + '\\033[0m'+\", he had a chance to win the race becouse he did a great job in the last parts of the game!\")\n                    if jockey_position>3:\n                        last_better='yes'\n                        print(f\"However, he was the last jockey in some part of \"+'\\033[1m'+Fore.GREEN + f\"{list(position_max[position_max==(len(L)-1)].index)}.\" + '\\033[0m'+\", he had a chance to finish the race with a better end position becouse he did a great job in the last parts of the game!\")\n\n            if  last_better!='yes':\n                first_position_i=list(position_minr[position_minr[0]==0].index)[-1]\n                if first_position_i>=position_min.shape[0]-2 and jockey_position!=1:\n                    print(\"So, he had a chance to win the race!\")\n                if first_position_i<position_min.shape[0]-2:\n                    print(\"But, he couldn't keep this position in the last parts of the track!\")\n        win=[i for i,j in enumerate(SDFl[0]) if j==-100]\n\n        if len(win)!=0 and win[0]>=3 and jockey_position>=2 and SDFl[0][-1]>0 and SDFl[0][-2]>0:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"As it was mentioned, he was in the first position in the \"+'\\033[1m'+Fore.GREEN + f\"{win[0]+1}.\" + '\\033[0m'+\"-th part of the race but his distance with further compatitors increased significantly in the last two parts of the race. In those parts, His average speed was lower than general average rate! \")        \n            p=p+1\n        if SDFl[0][-1]>0 and SDFl[0][-2]>0 and jockey_position!=1:\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"According to the two last parts of the race (i.e \"+'\\033[1m'+Fore.GREEN + f\"{race_parts[:race_shapeN][-1]},{race_parts[:race_shapeN][-2]},.\" + '\\033[0m'+\" ), the jockey couldn't finish the race with a better position becouse his distance with further compatitors was larger than average rate. \\n\")\n            p=p+1\n        if SDBl[0][-1]<0 and SDBl[0][-2]<0 and jockey_position!=len(L):\n            print(f'\\033[1m'+Fore.BLACK + f\"Point {p}:\" + '\\033[0m' + f\"According to the two last parts of the race (i.e \"+'\\033[1m'+Fore.GREEN + f\"{race_parts[:race_shapeN][-1]},{race_parts[:race_shapeN][-2]},.\" + '\\033[0m'+\"), the jockey could finish the race with a worth position becouse his distance with bihind compatitors was closer than average rate. \\n\")\n            p=p+1\n\n\n\n\n        print(Fore.BLUE +'\\033[1m'+ ' \\n Visualization: ' +'\\033[0m' +'\\n')\n        for i,k in zip(range(len(L)),['red','black','green','pink','grey','yellow','blue','orange','purple']):\n            X = np.arange(0, len(L[i]), 1)\n            plt.plot(X, window(L[i],'speed')['window'], color=k, label=str(i+1)+'th end position')\n        plt.title(\"The speed graph of jockeys in the race with moving average 30\")\n        plt.legend(loc=\"upper left\")\n        plt.show() \n        print(indS)\n        positions1=positions.reset_index()\n        ax1 = positions1[:indS].plot(kind='scatter', x='index', y='1th', color='red',figsize=(15,8)) \n        for i,j in zip(range(1,len(L)+1),['red','black','green','pink','grey','yellow','blue','orange','purple']):   \n            ax2 = positions1[:indS].plot(kind='scatter', x='index', y=str(i)+'th', color=j, ax=ax1,figsize=(15,8),label=str(i)+'th end position') \n        plt.legend(loc=\"upper left\")\n","metadata":{"execution":{"iopub.status.busy":"2022-12-03T01:11:08.996936Z","iopub.execute_input":"2022-12-03T01:11:08.997280Z","iopub.status.idle":"2022-12-03T01:11:16.165205Z","shell.execute_reply.started":"2022-12-03T01:11:08.997249Z","shell.execute_reply":"2022-12-03T01:11:16.164292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Simply enter the name of the race (`BEL`,`AQU` or `SAR`), the date, time and an arbitrary end position of the game in the following function and see the result!!**","metadata":{}},{"cell_type":"code","source":"race='SAR'\ndate='2019-09-02'\ntime=540\njockey_position=4\nmain_Algorithm(data,all_Jockeys_data,race,date,time,jockey_position)","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2022-12-03T01:14:54.169196Z","iopub.execute_input":"2022-12-03T01:14:54.169676Z","iopub.status.idle":"2022-12-03T01:14:57.620080Z","shell.execute_reply.started":"2022-12-03T01:14:54.169638Z","shell.execute_reply":"2022-12-03T01:14:57.619020Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Conclusions**\n\n* The winner dosn't have the highest speed in the race necessarily.\n* program id or track condition or some other attributes that were mentioned in the main algorithm, will not increase/decrease the chance of win in general! But it depends on jockeys! For example a jockey might do a better job in a specific program id.\n* The last part of the race (`Secend_Straight_Way` in half_Elipsoide_Shape and `Third_Straight_Way` in Elipsoide_Shape ) are very important. If the horse can speed up in these parts, the chance of win increases significantly.\n* The distance of jockeys with behind and further compatitors is important. If the distance get less/more than average rate, the chance of win/loss increases.\n* All I used in this notebook is mathematics and statistics ","metadata":{}},{"cell_type":"markdown","source":"# Further Work\nMore details can be added to the Main Algorithm and it can be more inteligence.","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}