%run "../Functions/1. Google form analysis.ipynb"
%run "../Functions/4. User comparison.ipynb"

"""
Explanation: User comparison tests
Table of Contents
Preparation
User data vectors
User lists
Sessions' checkpoints
Assembly
Time
Preparation
<a id=preparation />
End of explanation
"""


#getAllResponders()

setAnswerTemporalities(gform)

"""
Explanation: Data vectors of users
<a id=userdatavectors />
End of explanation
"""


# small sample
#allData = getAllUserVectorData( getAllUsers( rmdf1522 )[:10] )

# complete set
#allData = getAllUserVectorData( getAllUsers( rmdf1522 ) )

# subjects who answered the gform
allData = getAllUserVectorData( getAllResponders() )

# 10 subjects who answered the gform
#allData = getAllUserVectorData( getAllResponders()[:10] )

efficiencies = allData.loc['efficiency'].sort_values()
efficiencies.index = range(0, len(allData.columns))
efficiencies.plot(title = 'efficiency')

efficiencies2 = allData.loc['efficiency'].sort_values()
efficiencies2 = efficiencies2[efficiencies2 != 0]
efficiencies2.index = range(0, len(efficiencies2))
efficiencies2 = np.log(efficiencies2)
efficiencies2.plot(title = 'efficiency log')

maxChapter = allData.loc['maxChapter'].sort_values()
maxChapter.index = range(0, len(allData.columns))
maxChapter.plot(title = 'maxChapter')

len(allData.columns)

userIds = getAllResponders()
_source = correctAnswers

# _source is used as correction source, if we want to include answers to these questions
#def getAllUserVectorData( userIds, _source = [] ):
    
# result
isInitialized = False
allData = []

f = FloatProgress(min=0, max=len(userIds))
display(f)

for userId in userIds:
    #print(str(userId))
    f.value += 1
    if not isInitialized:
        isInitialized = True
        allData = getUserDataVector(userId, _source = _source)
    else:
        allData = pd.concat([allData, getUserDataVector(userId, _source = _source)], axis=1)

#print('done')
allData

userId

"""
Explanation: getAllUserVectorData
End of explanation
"""


methods = ['pearson', 'kendall', 'spearman']

_allUserVectorData = allData.T
_method = methods[0]
_title='RedMetrics Correlations'
_abs=True
_clustered=False
_figsize = (20,20)


#def plotAllUserVectorDataCorrelationMatrix(
#    _allUserVectorData,
#    _method = methods[0], 
#    _title='RedMetrics Correlations', 
#    _abs=False,
#    _clustered=False, 
#    _figsize = (20,20)
#):
    
_progress = FloatProgress(min=0, max=3)
display(_progress)

# computation of correlation matrix
_m = _method
if(not (_method in methods)):
    _m = methods[0]
_correlation = _allUserVectorData.astype(float).corr(_m)
_progress.value += 1
if(_abs):
    _correlation = _correlation.abs()
_progress.value += 1

# plot
if(_clustered):
    sns.clustermap(_correlation,cmap=plt.cm.jet,square=True,figsize=_figsize)
else:
    _fig = plt.figure(figsize=_figsize)
    _ax = plt.subplot(111)
    _ax.set_title(_title)
    sns.heatmap(_correlation,ax=_ax,cmap=plt.cm.jet,square=True)
_progress.value += 1

gform[QTemporality].unique()

allData.loc['scoreundefined'].dropna()

getAllUsers(rmdf1522)[:10]

len(getAllUsers(rmdf1522))

"""
Explanation: Correlation Matrix
End of explanation
"""


userSessionsRelevantColumns = ['customData.localplayerguid', 'sessionId']
userSessions = rmdf1522[rmdf1522['type']=='start'].loc[:,userSessionsRelevantColumns]

userSessions = userSessions.rename(index=str, columns={'customData.localplayerguid': 'userId'})
userSessions.head()

#groupedUserSessions = userSessions.groupby('customData.localplayerguid')
#groupedUserSessions.head()
#groupedUserSessions.describe().head()

"""
Explanation: List of users and their sessions
<a id=userlists />
End of explanation
"""


checkpointsRelevantColumns = ['sessionId', 'customData.localplayerguid', 'type', 'section', 'userTime']
checkpoints = rmdf1522.loc[:, checkpointsRelevantColumns]

checkpoints = checkpoints[checkpoints['type']=='reach'].loc[:,['section','sessionId','userTime']]
checkpoints = checkpoints[checkpoints['section'].str.startswith('tutorial', na=False)]
#checkpoints = checkpoints.groupby("sessionId")
#checkpoints = checkpoints.max()
checkpoints.head()

"""
Explanation: List of sessions with their checkpoints achievements
<a id=sessionscheckpoints />
End of explanation
"""


#assembled = userSessions.combine_first(checkpoints)
assembled = pd.merge(userSessions, checkpoints, on='sessionId', how='outer')
assembled.head()

userSections = assembled.drop('sessionId', 1)
userSections.head()

userSections = userSections.dropna()
userSections.head()

checkpoints = userSections.groupby("userId")
checkpoints = checkpoints.max()
checkpoints.head()

"""
Explanation: Assembly of both
<a id=assembly />
End of explanation
"""


#userTimedSections = userSections.groupby("userId").agg({ "userTime": np.min })
#userTimedSections = userSections.groupby("userId")
userTimes = userSections.groupby("userId").agg({ "userTime": [np.min, np.max] })
userTimes["duration"] = pd.to_datetime(userTimes["userTime"]["amax"]) - pd.to_datetime(userTimes["userTime"]["amin"])
userTimes["duration"] = userTimes["duration"].map(lambda x: np.timedelta64(x, 's'))
userTimes = userTimes.sort_values(by=['duration'], ascending=[False])
userTimes.head()

"""
Explanation: Time analysis
<a id=time />
End of explanation
"""


sessionCount = 1
_rmDF = rmdf1522
sample = gform
before = False
after = True
gfMode = False
rmMode = True

#def getAllUserVectorDataCustom(before, after, gfMode = False, rmMode = True, sessionCount = 1, _rmDF = rmdf1522)
userIds = []

if (before and after):
    userIds = getSurveysOfUsersWhoAnsweredBoth(sample, gfMode = gfMode, rmMode = rmMode)
elif before:
    if rmMode:
        userIds = getRMBefores(sample)
    else:
        userIds = getGFBefores(sample)
elif after:
    if rmMode:
        userIds = getRMAfters(sample)
    else:
        userIds = getGFormAfters(sample)
if(len(userIds) > 0):
    userIds = userIds[localplayerguidkey]
    allUserVectorData = getAllUserVectorData(userIds, _rmDF = _rmDF)
    allUserVectorData = allUserVectorData.T
    result = allUserVectorData[allUserVectorData['sessionsCount'] == sessionCount].T

else:
    print("no matching user")
    result = []

result

getAllUserVectorDataCustom(False, True)

userIdsBoth = getSurveysOfUsersWhoAnsweredBoth(gform, gfMode = True, rmMode = True)[localplayerguidkey]
allUserVectorData = getAllUserVectorData(userIdsBoth)
allUserVectorData = allUserVectorData.T
allUserVectorData[allUserVectorData['sessionsCount'] == 1]

"""
Explanation: TODO
userTimes.loc[:,'duration']
userTimes = userTimes[4:]
userTimes["duration_seconds"] = userTimes["duration"].map(lambda x: pd.Timedelta(x).seconds)
maxDuration = np.max(userTimes["duration_seconds"])
userTimes["duration_rank"] = userTimes["duration_seconds"].rank(ascending=False)
userTimes.plot(x="duration_rank", y="duration_seconds")
plt.xlabel("game session")
plt.ylabel("time played (s)")
plt.legend('')
plt.xlim(0, 139)
plt.ylim(0, maxDuration)
userTimedSections = userSections.groupby("section").agg({ "userTime": np.min })
userTimedSections
userTimedSections["firstReached"] = pd.to_datetime(userTimedSections["userTime"])
userTimedSections.head()
userTimedSections.drop('userTime', 1)
userTimedSections.head()
userTimedSections["firstCompletionDuration"] = userTimedSections["firstReached"].diff()
userTimedSections.head()
End of explanation
"""


testUser = "3685a015-fa97-4457-ad73-da1c50210fe1"

def getScoreFromBinarized(binarizedAnswers):
    gformIndices = binarizedAnswers.index.map(lambda s: int(s.split(correctionsColumnNameStem)[1]))
    return pd.Series(np.dot(binarizedAnswers, np.ones(binarizedAnswers.shape[1])), index=gform.loc[gformIndices, localplayerguidkey])    

#allResponders = getAllResponders()

#gf_both = getSurveysOfUsersWhoAnsweredBoth(gform, gfMode = True, rmMode = False)
rm_both = getSurveysOfUsersWhoAnsweredBoth(gform, gfMode = False, rmMode = True)
#gfrm_both = getSurveysOfUsersWhoAnsweredBoth(gform, gfMode = True, rmMode = True)

sciBinarizedBefore = getAllBinarized(_form = getRMBefores(rm_both))
sciBinarizedAfter = getAllBinarized(_form = getRMAfters(rm_both))

scoresBefore = getScoreFromBinarized(sciBinarizedBefore)
scoresAfter = getScoreFromBinarized(sciBinarizedAfter)

medianBefore = np.median(scoresBefore)
medianAfter = np.median(scoresAfter)
maxScore = sciBinarizedBefore.shape[1]

indicators = pd.DataFrame()
indicators[answerTemporalities[0]] = scoresBefore
indicators[answerTemporalities[1]] = scoresAfter

indicators['delta'] = scoresAfter - scoresBefore
indicators['maxPotentialDelta'] = maxScore - scoresBefore
for index in indicators['maxPotentialDelta'].index:
    if (indicators.loc[index, 'maxPotentialDelta'] == 0):
        indicators.loc[index, 'maxPotentialDelta'] = 1 

indicators['relativeBefore'] = scoresBefore / medianBefore
indicators['relativeAfter'] = scoresAfter / medianBefore
indicators['relativeDelta'] = indicators['delta'] / medianBefore
indicators['realizedPotential'] = indicators['delta'] / indicators['maxPotentialDelta']
indicators['increaseRatio'] = indicators[answerTemporalities[0]]
for index in indicators['increaseRatio'].index:
    if (indicators.loc[index, 'increaseRatio'] == 0):
        indicators.loc[index, 'increaseRatio'] = 1 
indicators['increaseRatio'] = indicators['delta'] / indicators['increaseRatio']

indicators

(min(indicators['relativeBefore']), max(indicators['relativeBefore'])),\
(min(indicators['relativeDelta']), max(indicators['relativeDelta'])),\
medianBefore,\
np.median(indicators['relativeBefore']),\
np.median(indicators['relativeDelta'])\

indicatorX = 'relativeBefore'
indicatorY = 'relativeDelta'

def scatterPlotIndicators(indicatorX, indicatorY):
    
    print(indicatorX + ' range: ' + str((min(indicators[indicatorX]), max(indicators[indicatorX]))))
    print(indicatorY + ' range: ' + str((min(indicators[indicatorY]), max(indicators[indicatorY]))))
    print(indicatorX + ' median: ' + str(np.median(indicators[indicatorX])))
    print(indicatorY + ' median: ' + str(np.median(indicators[indicatorY])))
    
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    ax1.scatter(indicators[indicatorX], indicators[indicatorY])
    plt.xlabel(indicatorX)
    plt.ylabel(indicatorY)

    # vertical line
    plt.plot(   [np.median(indicators[indicatorX]), np.median(indicators[indicatorX])],\
                [min(indicators[indicatorY]), max(indicators[indicatorY])],\
             'k-', lw=2)

    # horizontal line
    plt.plot(   [min(indicators[indicatorX]), max(indicators[indicatorX])],\
                [np.median(indicators[indicatorY]), np.median(indicators[indicatorY])],\
             'k-', lw=2)

indicators.columns

scatterPlotIndicators('relativeBefore', 'relativeDelta')

scatterPlotIndicators('relativeBefore', 'realizedPotential')

scatterPlotIndicators('relativeBefore', 'increaseRatio')

scatterPlotIndicators('relativeBefore', 'relativeAfter')

scatterPlotIndicators('maxPotentialDelta', 'realizedPotential')

"""
Explanation: user progress classification
tinkering
End of explanation
"""


