Skip to content
Snippets Groups Projects
Commit ab408999 authored by Stuart Hallifax's avatar Stuart Hallifax
Browse files

Renamed Action to Observation. Added timesince last update to Observations....

Renamed Action to Observation. Added timesince last update to Observations. Added GameElementUpdate Operation.
parent e021de8e
Branches master
No related tags found
No related merge requests found
......@@ -65,7 +65,7 @@ if __name__ == "__main__" :
transformedTimeline = transformOperation(todayTimeline)
selectedUser.actionsPerformed = transformedTimeline
selectedUser.observations = transformedTimeline
for action in transformedTimeline:
print(action)
......@@ -8,11 +8,11 @@ GameElement = NewType("GameElement", str)
#TODO: Renommer les classes en "Observation" - changer le nom du fichier (refactor)
#TODO : Créer une classe remonter depuis un quiz avec un attribut qui donne jusqu'ou on remonte (section, course). Pour les Observations Visiter la page X pendant un quiz
#TODO : Ajouter l'attribut date since last game element update
class Action:
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement):
class Observation:
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, previousUpdate: datetime):
"""
:param start: A datetime at the start of the Action
......@@ -25,9 +25,13 @@ class Action:
self.user = user
self.gameElement = gameElement
self.actionName = "Action"
self.previousUpdate = previousUpdate
def __str__(self):
return str(self.actionName) + ";" + str(self.user.name) + ";" + str(self.gameElement) + ";" + str(self.start) + ";" + str(self.end) + ";"
if self.previousUpdate is None:
return str(self.actionName) + ";" + str(self.user.name) + ";" + str(self.gameElement) + ";" + str(self.start) + ";" + str(self.end) + "; ;"
else :
return str(self.actionName) + ";" + str(self.user.name) + ";" + str(self.gameElement) + ";" + str(self.start) + ";" + str(self.end) + ";" + str(self.start-self.previousUpdate) + ";"
def __lt__(self, other):
......@@ -38,8 +42,8 @@ class Action:
else:
return self.end < other.end
class Pause(Action):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, op1: Operation, op2: Operation):
class Pause(Observation):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, op1: Operation, op2: Operation, previousUpdate: datetime):
"""
:param start: A datetime at the start of the Action
......@@ -49,7 +53,7 @@ class Pause(Action):
:param op1: The first operation
:param op2: The second operation
"""
super().__init__(start, end, user, gameElement)
super().__init__(start, end, user, gameElement, previousUpdate)
self.op1 = op1
self.op2 = op2
self.actionName = "Pause"
......@@ -64,8 +68,8 @@ class Pause(Action):
"""
return self.end - self.start
class AttemptQuiz(Action):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, quizId: str, attemptNumber: int):
class AttemptQuiz(Observation):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, quizId: str, attemptNumber: int, previousUpdate: datetime):
"""
:param start: A datetime at the start of the Action
......@@ -75,7 +79,7 @@ class AttemptQuiz(Action):
:param quizId: The Id of the attempted quiz
:param attemptNumber: The attempt number
"""
super().__init__(start, end, user, gameElement)
super().__init__(start, end, user, gameElement, previousUpdate)
self.quizId = quizId
self.attemptNumber = attemptNumber
self.actionName = "AttemptQuiz"
......@@ -83,8 +87,8 @@ class AttemptQuiz(Action):
def __str__(self):
return super().__str__() + "QuizId:"+ self.quizId + ";" + "Attempt:" + str(self.attemptNumber)
class ResumeQuizAttempt(Action):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, quizId: str, attemptNumber: int):
class ResumeQuizAttempt(Observation):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, quizId: str, attemptNumber: int, previousUpdate: datetime):
"""
:param start: A datetime at the start of the Action
......@@ -94,7 +98,7 @@ class ResumeQuizAttempt(Action):
:param quizId: The Id of the attempted quiz
:param attemptNumber: The attempt number
"""
super().__init__(start, end, user, gameElement)
super().__init__(start, end, user, gameElement, previousUpdate)
self.quizId = quizId
self.attemptNumber = attemptNumber
self.actionName = "ResumeQuizAttempt"
......@@ -102,8 +106,8 @@ class ResumeQuizAttempt(Action):
def __str__(self):
return super().__str__() + "QuizId:"+ self.quizId + ";" + "Attempt:" + str(self.attemptNumber)
class CompleteQuestion(Action):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, success: bool = True):
class CompleteQuestion(Observation):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, previousUpdate: datetime, success: bool = True):
"""
:param start: A datetime at the start of the Action
......@@ -112,15 +116,15 @@ class CompleteQuestion(Action):
:param gameElement: The game element that the user had when the performed the Action
:param success: Whether the question was answered correctly or not
"""
super().__init__(start, end, user, gameElement)
super().__init__(start, end, user, gameElement, previousUpdate)
self.success = success
self.actionName = "CompleteQuestion"
def __str__(self):
return super().__str__() + "Success:" + str(self.success)
class CompleteQuiz(Action):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, quizId: str, attemptNumber: int, interruption: bool = False, success: bool = True):
class CompleteQuiz(Observation):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, quizId: str, attemptNumber: int, previousUpdate: datetime, interruption: bool = False, success: bool = True):
"""
......@@ -133,7 +137,7 @@ class CompleteQuiz(Action):
:param interruption: Indicate whether the quiz was interrupted or not
:param success: Indicate whether the student validated the quiz or not
"""
super().__init__(start, end, user, gameElement)
super().__init__(start, end, user, gameElement, previousUpdate)
self.quizId = quizId
self.attemptNumber = attemptNumber
self.interruption = interruption
......@@ -144,8 +148,8 @@ class CompleteQuiz(Action):
def __str__(self):
return super().__str__() + "QuizId:"+ self.quizId + ";" + "Attempt:" + str(self.attemptNumber) + ";Interruption:" + str(self.interruption) + ";Success:" + str(self.success)
class RestartQuiz(Action):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, quizId: str, attemptNumber: int, afterSuccess: bool = False,
class RestartQuiz(Observation):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, quizId: str, attemptNumber: int, previousUpdate: datetime, afterSuccess: bool = False,
inCurrentLesson: bool = True,
interruptCurrentLesson: bool = False):
"""
......@@ -160,7 +164,7 @@ class RestartQuiz(Action):
:param inCurrentLesson: Indicate whether the quiz was restarted during a later lesson
:param interruptCurrentLesson: Indicate whether the quiz was restarted before the current lesson was completed
"""
super().__init__(start, end, user, gameElement)
super().__init__(start, end, user, gameElement, previousUpdate)
self.quizId = quizId
self.attemptNumber = attemptNumber
self.afterSuccess = afterSuccess
......@@ -171,9 +175,9 @@ class RestartQuiz(Action):
def __str__(self):
return super().__str__() + "QuizId:"+ self.quizId + ";" + "Attempt:" + str(self.attemptNumber) + ";AfterSuccess:" + str(self.afterSuccess) + ";InCurrentLesson:" + str(self.inCurrentLesson) + ";InterruptCurrentLesson:" + str(self.interruptCurrentLesson)
class AbandonQuiz(Action):
class AbandonQuiz(Observation):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, quizId: str,
attemptNumber: int, numberOfQuestions: int, correctQuestions: int):
attemptNumber: int, numberOfQuestions: int, correctQuestions: int, previousUpdate: datetime):
"""
:param start: A datetime at the start of the Action
......@@ -185,7 +189,7 @@ class AbandonQuiz(Action):
:param numberOfQuestions: The number of attempted questions
:param correctQuestions: The number of correct questions
"""
super().__init__(start, end, user, gameElement)
super().__init__(start, end, user, gameElement, previousUpdate)
self.quizId = quizId
self.attemptNumber = attemptNumber
self.numberOfQuestions = numberOfQuestions
......@@ -195,8 +199,8 @@ class AbandonQuiz(Action):
def __str__(self):
return super().__str__() + "QuizId:" + self.quizId + ";Attempt:" + str(self.attemptNumber) + ";NumberOfQuestions:" + str(self.numberOfQuestions) + ";CorrectionQuestions" + str(self.correctQuestions)
class StartLesson(Action):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, lessonId: str):
class StartLesson(Observation):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, lessonId: str, previousUpdate: datetime):
"""
:param start: A datetime at the start of the Action
......@@ -205,15 +209,15 @@ class StartLesson(Action):
:param gameElement: The game element that the user had when the performed the Action
:param lessonId: The Id of the lesson started
"""
super().__init__(start, end, user, gameElement)
super().__init__(start, end, user, gameElement, previousUpdate)
self.lessonId = lessonId
self.actionName = "StartLesson"
def __str__(self):
return super().__str__() + "LessonId:"+ self.lessonId
class CompleteLesson(Action):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, lessonId: str, success: bool = True):
class CompleteLesson(Observation):
def __init__(self, start: datetime, end: datetime, user: User, gameElement: GameElement, lessonId: str, previousUpdate: datetime, success: bool = True):
"""
:param start: A datetime at the start of the Action
......@@ -223,7 +227,7 @@ class CompleteLesson(Action):
:param lessonId: The Id of the lesson started
:param success: Has the lesson been completed fully or not
"""
super().__init__(start, end, user, gameElement)
super().__init__(start, end, user, gameElement, previousUpdate)
self.lessonId = lessonId
self.success = success
self.actionName = "CompleteLesson"
......
from datetime import datetime
from User import User
def buildOperation(logRow, user):
#Row structure
......@@ -45,7 +45,8 @@ def buildOperation(logRow, user):
return QuizResults(timestamp, user, gameElement, parameters[0], parameters[1])
#Game element related trace
#TODO : Ajouter Operation _update (Mise a jour de l'élément ludique)
elif "_update" in op:
return GameElementUpdate(timestamp, user, gameElement)
#TODO: Les Operations Visiter Calendrier, Page de prefs, page de profil
......@@ -182,4 +183,17 @@ class QuizResults(Operation):
self.quizResults = quizResults
def __str__(self):
return "Quiz results :" + self.timestamp.strftime('%Y-%m-%d %H:%M:%S') + self.quizId + self.attemptNumber + self.quizResults
\ No newline at end of file
return "Quiz results :" + self.timestamp.strftime('%Y-%m-%d %H:%M:%S') + self.quizId + self.attemptNumber + self.quizResults
class GameElementUpdate(Operation):
def __init__(self, timestamp: datetime, user: User, gameElement: str):
"""
:param timestamp:
:param user:
:param gameElement:
"""
super().__init__(timestamp, user, gameElement)
def __str__(self):
return "Game element update : " + self.timestamp.strftime('%Y-%m-%d %H:%M:%S')
\ No newline at end of file
from Traces.Operation import *
from Traces.Action import *
from Traces.Observation import *
from datetime import timedelta
# STATIC VALUES
pauseDelta = timedelta(seconds=5)
pauseDelta = timedelta(minutes=2)
passRate = 0.7 #The % of correct answers to consider that a quiz is successful
def transformOperation(timeline):
......@@ -20,7 +20,7 @@ def transformOperation(timeline):
correctQuestions = 0.0
previousQuizzes = {}
success = ''
lastUpdate = None
timestamps = sorted(timeline.keys())
i = 0
......@@ -33,9 +33,14 @@ def transformOperation(timeline):
# Get current operation
op : Operation = timeline[timestamps[i]]
if type(op) is GameElementUpdate:
lastUpdate = op.timestamp
i = i+1
continue
if not inQuiz:
if type(op) in [QuizPageview]:
transformedTimeline.append(ResumeQuizAttempt(op.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber))
transformedTimeline.append(ResumeQuizAttempt(op.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber, lastUpdate))
quizStart = op
inQuiz = True
interruptedQuiz = True
......@@ -59,8 +64,8 @@ def transformOperation(timeline):
interruptedQuiz = True
if (type(op) is QuizPageview) and (op.quizId != quizStart.quizId):
transformedTimeline.append(AbandonQuiz(op.timestamp, op.timestamp, op.user, op.gameElement, quizStart.quizId, quizStart.attemptNumber, numberOfQuestions, correctQuestions))
transformedTimeline.append(ResumeQuizAttempt(op.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber))
transformedTimeline.append(AbandonQuiz(op.timestamp, op.timestamp, op.user, op.gameElement, quizStart.quizId, quizStart.attemptNumber, numberOfQuestions, correctQuestions, lastUpdate))
transformedTimeline.append(ResumeQuizAttempt(op.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber, lastUpdate))
quizStart = op
inQuiz = True
interruptedQuiz = True
......@@ -82,7 +87,7 @@ def transformOperation(timeline):
# Pause check
if timestamps[i] - timestamps[i-1] >= pauseDelta:
transformedTimeline.append(Pause(timestamps[i-1], timestamps[i], op.user, op.gameElement, previousOp, op))
transformedTimeline.append(Pause(timestamps[i-1], timestamps[i], op.user, op.gameElement, previousOp, op, lastUpdate))
i+=1
continue
......@@ -90,12 +95,12 @@ def transformOperation(timeline):
if (type(op) is QuizAttemptStarted) and (type(previousOp) is QuizModuleview):
#if op.quizId == previousOp.quizId: #This check doesn't currently work as ids don't match !
if inQuiz:
transformedTimeline.append(AbandonQuiz(previousOp.timestamp, op.timestamp, op.user, op.gameElement, quizStart.quizId, quizStart.attemptNumber, numberOfQuestions, correctQuestions))
transformedTimeline.append(AbandonQuiz(previousOp.timestamp, op.timestamp, op.user, op.gameElement, quizStart.quizId, quizStart.attemptNumber, numberOfQuestions, correctQuestions, lastUpdate))
if op.quizId not in previousQuizzes.keys():
transformedTimeline.append(AttemptQuiz(previousOp.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber))
transformedTimeline.append(AttemptQuiz(previousOp.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber, lastUpdate))
else:
transformedTimeline.append(RestartQuiz(previousOp.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber, previousQuizzes[op.quizId]))
transformedTimeline.append(RestartQuiz(previousOp.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber, lastUpdate, previousQuizzes[op.quizId], lastUpdate))
quizStart = op
inQuiz = True
......@@ -113,7 +118,7 @@ def transformOperation(timeline):
# Complete question check
if (type(op) in [QuestionGradedRight, QuestionGradedWrong]) and (type(previousOp) is QuizPageview):
if op.quizId == previousOp.quizId:
transformedTimeline.append(CompleteQuestion(previousOp.timestamp, op.timestamp, op.user, op.gameElement, type(op) is QuestionGradedRight))
transformedTimeline.append(CompleteQuestion(previousOp.timestamp, op.timestamp, op.user, op.gameElement, lastUpdate, type(op) is QuestionGradedRight))
i+=1
numberOfQuestions += 1
......@@ -129,7 +134,7 @@ def transformOperation(timeline):
if success != "Unsure" :
success = correctQuestions/numberOfQuestions > passRate
transformedTimeline.append(CompleteQuiz(quizStart.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber, interruptedQuiz, success))
transformedTimeline.append(CompleteQuiz(quizStart.timestamp, op.timestamp, op.user, op.gameElement, op.quizId, op.attemptNumber, lastUpdate, interruptedQuiz, success))
inQuiz = False
interruptedQuiz = False
......
import User.UserProfileData as upd
from Traces.Action import *
from Traces.Observation import *
class User:
def __init__(self, name, gameElement, userProfileData = upd.UserProfileData(0,0,0,0)):
......@@ -7,7 +7,7 @@ class User:
self.gameElements = [gameElement]
self.currentGameElement = gameElement
self.operationsPerformed = {}
self.actionsPerformed = {}
self.observations = {}
self.userProfile = userProfileData
def addGameElement(self, gameElement):
......@@ -39,17 +39,17 @@ class User:
def getNumberOfPauses(self):
i = 0
for timestamp in self.actionsPerformed :
if type(self.actionsPerformed[timestamp]) is Pause:
for timestamp in self.observations :
if type(self.observations[timestamp]) is Pause:
i+=1
return i
def exportActions(self):
output = "Action;User;GameElement;Debut;Fin;Infos\n"
def exportObservations(self):
output = "Action;User;GameElement;Debut;Fin;Time since last update;Infos\n"
with open("transformedTrace.csv", 'w') as file:
for action in self.actionsPerformed:
output += str(action) + "\n"
for observation in self.observations:
output += str(observation) + "\n"
file.write(output)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment