{"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":"markdown","source":"# Intro\nHello, in this notebook, my aim is to analyze the duration of players' engagement in mini-tasks and the number of events that occur from the beginning of the task until its completion. The goal is to gain insight into how players interact with the game. Sure!\nIn the following images, we will be examining the data related to tasks that players need to complete to progress through the game. There are a total of 10 tasks at present. Let's begin implementing the notebook.","metadata":{}},{"cell_type":"markdown","source":"![](https://i.ibb.co/TkGrQf9/merge-from-ofoct.jpg)","metadata":{}},{"cell_type":"markdown","source":"# Imports","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport matplotlib.pyplot as plt","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-04-16T06:31:17.378862Z","iopub.execute_input":"2023-04-16T06:31:17.379238Z","iopub.status.idle":"2023-04-16T06:31:17.411571Z","shell.execute_reply.started":"2023-04-16T06:31:17.379203Z","shell.execute_reply":"2023-04-16T06:31:17.410661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Loading dataset\nTo successfully load the dataframe, we will use categories and other types and the columns we need","metadata":{}},{"cell_type":"code","source":"use_columns = ['session_id', \n               'text_fqid', \n               'elapsed_time', 'event_name','room_fqid','name','fqid','text','index']\ndtypes={'session_id':'category', \n'elapsed_time':np.int32,\n    'event_name':'category',\n    'name':'category',\n    'level':np.uint8,\n    'page':'category',\n    'room_coor_x':np.float32,\n    'room_coor_y':np.float32,\n    'screen_coor_x':np.float32,\n    'screen_coor_y':np.float32,\n    'hover_duration':np.float32,\n     'text':'category',\n     'fqid':'category',\n     'room_fqid':'category',\n     'text_fqid':'category',\n     'fullscreen':'category',\n     'hq':'category',\n     'music':'category',\n     'level_group':'category'}\ndf = pd.read_csv('/kaggle/input/predict-student-performance-from-game-play/train.csv', \n                 dtype=dtypes, usecols=use_columns)\n","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:31:17.418810Z","iopub.execute_input":"2023-04-16T06:31:17.419478Z","iopub.status.idle":"2023-04-16T06:32:54.297086Z","shell.execute_reply.started":"2023-04-16T06:31:17.419437Z","shell.execute_reply":"2023-04-16T06:32:54.295838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:54.299162Z","iopub.execute_input":"2023-04-16T06:32:54.299710Z","iopub.status.idle":"2023-04-16T06:32:54.330956Z","shell.execute_reply.started":"2023-04-16T06:32:54.299674Z","shell.execute_reply":"2023-04-16T06:32:54.329905Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Choice of criteria\nIdentifying the relevant game tasks from the dataset was challenging, but we were able to accomplish it! Our approach was to identify the events responsible for initiating each game task. This was determined by the corresponding 'fquid' value. To pinpoint the time and location where the player solved the task, we relied on the associated 'text' value. Below, we present the results of our analysis.","metadata":{}},{"cell_type":"markdown","source":"**Table of searching results**\n* 1)This looks like a clue!\t/tunic/ tunic.historicalsociety.collection \n* 2)That's it!\t/ plaque/ tunic.kohlcenter.halloffame )\n* 3)This place was around in 1916! I can start there!/ bbusinesscards/ \n* 4)It's a match!/ logbook/ tunic.drycleaner.frontdesk \n* 5)Youmans was a suffragist!/ reader / tunic.library.microfiche \n* 6)Hey, this is Youmans!/journals/ tunic.historicalsociety.stacks\t\n* 7)Those are the same glasses!/ directory.closeup.archivist/ tunic.historicalsociety.entry )\n* 8)That hoofprint doesn't match the flag!/ tracks/tunic.wildlife.center\n* 9)Hey! That's Governor Nelson in front of our flag!/reader_flag/tunic.library.microfiche\n* 10)Look at all those activists!/journals_flag/tunic.historicalsociety.stacks","metadata":{}},{"cell_type":"markdown","source":"To facilitate our analysis, we will transfer all the relevant data into an array. By grouping and sorting the data, we will generate a table that shows the duration of each task completion for each user. Furthermore, to determine the number of events that occurred during the completion of each mini-game, we will calculate the difference between the corresponding 'index'.\n\n","metadata":{}},{"cell_type":"markdown","source":"# Building a table","metadata":{}},{"cell_type":"code","source":"array_text = [\"This looks like a clue!\",\"That's it!\",\"This place was around in 1916! I can start there!\",\"It's a match!\",\"Youmans was a suffragist!\",\"Hey, this is Youmans!\",\"Those are the same glasses!\",\"That hoofprint doesn't match the flag!\",\"Hey! That's Governor Nelson in front of our flag!\",\"Look at all those activists!\"]\narray_fqid = [\"tunic\",\"plaque\",\"businesscards\",\"logbook\",\"reader\",\"journals\",\"directory.closeup.archivist\",\"tracks\",\"reader_flag\",\"journals_flag\"]","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:54.332292Z","iopub.execute_input":"2023-04-16T06:32:54.333213Z","iopub.status.idle":"2023-04-16T06:32:54.338954Z","shell.execute_reply.started":"2023-04-16T06:32:54.333176Z","shell.execute_reply":"2023-04-16T06:32:54.337679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"exit_time = df[df['text'] == 'This looks like a clue!'].groupby('session_id')['elapsed_time'].min().reset_index()\nexit_time['index1'] = df[df['text'] == 'This looks like a clue!'].groupby('session_id')['index'].min().reset_index()['index']\nexit_time['last'] = df[df['fqid'] == 'tunic'].groupby('session_id')['elapsed_time'].min().reset_index()['elapsed_time']\nexit_time['index2'] = df[df['fqid'] == 'tunic'].groupby('session_id')['index'].min().reset_index()['index']\nexit_time['l1'] = exit_time['elapsed_time'] - exit_time['last']\nexit_time['l1_ec'] = exit_time['index1'] - exit_time['index2'] + 1\nexit_time = exit_time[['session_id','l1','l1_ec']]\nfor i in range(0,10):\n    exit_time1 = df[df['text'] == array_text[i]].groupby('session_id')['elapsed_time'].min().reset_index()\n    exit_time1['index1'] = df[df['text'] == array_text[i]].groupby('session_id')['index'].min().reset_index()['index']\n    exit_time1['index2'] = df[df['fqid'] == array_fqid[i]].groupby('session_id')['index'].min().reset_index()['index']\n    exit_time1['last'] = df[df['fqid'] == array_fqid[i]].groupby('session_id')['elapsed_time'].min().reset_index()['elapsed_time']\n    exit_time['l' + str(i+1)] = exit_time1['elapsed_time'] - exit_time1['last']\n    exit_time['l' + str(i+1) +'_ec'] = exit_time1['index1'] - exit_time1['index2'] + 1\nexit_time\nexit_time","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:54.340678Z","iopub.execute_input":"2023-04-16T06:32:54.341378Z","iopub.status.idle":"2023-04-16T06:32:55.487705Z","shell.execute_reply.started":"2023-04-16T06:32:54.341339Z","shell.execute_reply":"2023-04-16T06:32:55.486490Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As we can see there are missing values in our column, let's count their number for each column","metadata":{}},{"cell_type":"code","source":"l_ec_columns = [col for col in exit_time.columns if col.startswith('l') and col.endswith('_ec')]\nfor col in l_ec_columns:\n    mode_value = exit_time[col].isna().sum()\n    print(\"Na/count {}: {}\".format(col, mode_value))","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:55.490432Z","iopub.execute_input":"2023-04-16T06:32:55.490948Z","iopub.status.idle":"2023-04-16T06:32:55.503691Z","shell.execute_reply.started":"2023-04-16T06:32:55.490917Z","shell.execute_reply":"2023-04-16T06:32:55.502603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Clue 1**","metadata":{}},{"cell_type":"code","source":"search_na_df= exit_time.set_index(exit_time['session_id'])\nsession_id = search_na_df[search_na_df['l1'].isna()].index[0]\nsession = df[df['session_id'] == session_id]\nsession.iloc[55:65]","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:55.504900Z","iopub.execute_input":"2023-04-16T06:32:55.505227Z","iopub.status.idle":"2023-04-16T06:32:55.548655Z","shell.execute_reply.started":"2023-04-16T06:32:55.505198Z","shell.execute_reply":"2023-04-16T06:32:55.547443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Clue 2**","metadata":{}},{"cell_type":"code","source":"session_id = search_na_df[search_na_df['l2'].isna()].index[0]\nsession = df[df['session_id'] == session_id]\nsession.iloc[125:135]","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:55.550205Z","iopub.execute_input":"2023-04-16T06:32:55.550753Z","iopub.status.idle":"2023-04-16T06:32:55.582658Z","shell.execute_reply.started":"2023-04-16T06:32:55.550713Z","shell.execute_reply":"2023-04-16T06:32:55.581149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Clue 3**","metadata":{}},{"cell_type":"code","source":"session_id = search_na_df[search_na_df['l3'].isna()].index[0]\nsession = df[df['session_id'] == session_id]\nsession.iloc[240:247]\n","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:55.584437Z","iopub.execute_input":"2023-04-16T06:32:55.584809Z","iopub.status.idle":"2023-04-16T06:32:55.611634Z","shell.execute_reply.started":"2023-04-16T06:32:55.584775Z","shell.execute_reply":"2023-04-16T06:32:55.610488Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As we can see, for some reason these users do not have the criteria by which we determine the beginning and end of the game, most likely this is due to data leakage, or directly to game errors.Replace missing values with medians","metadata":{}},{"cell_type":"code","source":"exit_time['l1'] = exit_time['l1'].fillna(exit_time['l1'].median())\nexit_time['l1_ec'] = exit_time['l1_ec'].fillna(exit_time['l1_ec'].median())\n\nexit_time['l1'] = exit_time['l1'].fillna(exit_time['l1'].median())\nexit_time['l1_ec'] = exit_time['l1_ec'].fillna(exit_time['l1_ec'].median())\n\nexit_time['l1'] = exit_time['l1'].fillna(exit_time['l3'].median())\nexit_time['l1_ec'] = exit_time['l1_ec'].fillna(exit_time['l1_ec'].median())","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:55.612877Z","iopub.execute_input":"2023-04-16T06:32:55.613377Z","iopub.status.idle":"2023-04-16T06:32:55.627330Z","shell.execute_reply.started":"2023-04-16T06:32:55.613342Z","shell.execute_reply":"2023-04-16T06:32:55.625874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Clue 7**\n","metadata":{}},{"cell_type":"markdown","source":"Let's take a look at why there are so many missing values in clue 7\nThere was an assumption that hint 7 can be skipped or bypassed, let's look at the options:\n* Descending to the basement is required\n1. The exit from the basement is immediately available (The board remains inactive, key will lie)\n2. You can click on the cell (The board remains inactive, key will lie)\n3. you can click on the raccoon(glasses can be picked up, else the game does not leave the room)\n\nTherefore, we are talking about either the loss of an array of data or the fact that the game was skipped in another way\n\n\n","metadata":{}},{"cell_type":"markdown","source":"Let's create a separate column that shows whether game 7 was skipped or not.\nFor simplicity, we will assume that if there is no data, then the game was skipped","metadata":{}},{"cell_type":"code","source":"exit_time['skip_l7'] = exit_time['l7'].isna()\nexit_time.head()","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:55.628644Z","iopub.execute_input":"2023-04-16T06:32:55.629178Z","iopub.status.idle":"2023-04-16T06:32:55.656409Z","shell.execute_reply.started":"2023-04-16T06:32:55.629143Z","shell.execute_reply":"2023-04-16T06:32:55.655674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"exit_time","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:55.657471Z","iopub.execute_input":"2023-04-16T06:32:55.657881Z","iopub.status.idle":"2023-04-16T06:32:55.692826Z","shell.execute_reply.started":"2023-04-16T06:32:55.657854Z","shell.execute_reply":"2023-04-16T06:32:55.691968Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Exciting news - our table is now complete, and contains data for each user regarding the completion of each mini-game. This data can be used to implement different models and support further research. \n\nNow, let's examine the average completion time for each of the mini-games and compare them. Additionally, let's look at the frequency of events occurring during the completion of each mini-game to gain a better understanding of the gameplay.","metadata":{}},{"cell_type":"code","source":"means = exit_time[['l1', 'l2', 'l3','l4','l5','l6','l7','l8','l9','l10']].mean()\nmeans.plot.bar()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:55.693941Z","iopub.execute_input":"2023-04-16T06:32:55.694374Z","iopub.status.idle":"2023-04-16T06:32:55.902280Z","shell.execute_reply.started":"2023-04-16T06:32:55.694344Z","shell.execute_reply":"2023-04-16T06:32:55.901476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"l_es_columns = ['l1_ec','l2_ec','l3_ec','l4_ec','l5_ec','l6_ec','l7_ec','l8_ec','l9_ec','l10_ec']\n\nfig, axs = plt.subplots(nrows=1, ncols=len(l_es_columns), figsize=(20, 5))\n\nfor i, col in enumerate(l_es_columns):\n    axs[i].hist(exit_time[col][exit_time[col] >= 0], bins=20)\n    axs[i].set_title(col)\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:55.903494Z","iopub.execute_input":"2023-04-16T06:32:55.903998Z","iopub.status.idle":"2023-04-16T06:32:57.075041Z","shell.execute_reply.started":"2023-04-16T06:32:55.903960Z","shell.execute_reply":"2023-04-16T06:32:57.073938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"l_ec_columns = [col for col in exit_time.columns if col.startswith('l') and col.endswith('_ec')]\n\nfor col in l_ec_columns:\n    mode_value = exit_time[col].mode().values[0]\n    print(\"The most frequent number of clicks in the block {}: {}\".format(col, mode_value))\n    ","metadata":{"execution":{"iopub.status.busy":"2023-04-16T06:32:57.078559Z","iopub.execute_input":"2023-04-16T06:32:57.078924Z","iopub.status.idle":"2023-04-16T06:32:57.090798Z","shell.execute_reply.started":"2023-04-16T06:32:57.078890Z","shell.execute_reply":"2023-04-16T06:32:57.089824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Completion\n**Thank you for taking the time to read my notebook! We have successfully created a comprehensive table that captures the time and number of events of each player for each task, and also analyzed some characteristics of the time and number of events. This notebook can serve as a starting point for your future research and modeling efforts.**\n\nIf you have any questions or notice any discrepancies in our approach or conclusions, please feel free to leave a comment. Thanks again and good luck with your research!","metadata":{}}]}