def receiveMessage(self, msg): #depending on the content of the message react differently #logInfo('Entering CSVReader.receiveMessage', 5) reply = None #Only considering if msg.getSpeechAct() == INFORM_ACT: if msg.getVerb() == ELECTRONIX_TUTOR_TASK_UPLOAD_VERB: logInfo('{0} is processing a {1},{2} message'.format(CSV_READER_SERVICE_NAME, ELECTRONIX_TUTOR_TASK_UPLOAD_VERB, INFORM_ACT), 4) csvString = msg.getResult() taskList = self.processCSVFile(csvString) print("STORAGE SERVICE NAME: %s"%(STORAGE_SERVICE_NAME)) reply = Message(STORAGE_SERVICE_NAME, VALUE_VERB, TASKS_OBJECT, taskList) if msg.getSpeechAct() == REQUEST_ACT: if msg.getVerb() == ELECTRONIX_TUTOR_TASK_UPLOAD_VERB: dbtaskList = DBTask.find_all() dbassistmentItemsList = DBAssistmentsItem.find_all() for dbTask in dbtaskList: if dbTask.assistmentsItemId is not None and dbTask.assistmentsItemId is not '': for dbassistmentsItem in dbassistmentItemsList: if dbassistmentsItem.id == dbTask.assistmentsItemId: dbTask.assistmentsItemCache = dbassistmentsItem break taskList = [x.toSerializable() for x in dbtaskList] reply = Message(CSV_READER_SERVICE_NAME, ELECTRONIX_TUTOR_TASK_UPLOAD_VERB, None, taskList, INFORM_ACT, msg.getContext()) if reply is not None: logInfo('{0} is broadcasting a {1}, {2} message'.format(CSV_READER_SERVICE_NAME, INFORM_ACT, VALUE_VERB), 4) self.sendMessage(reply)
def createSession(self, msg): logInfo("Could not find session with id:{0}. Creating new Session".format(msg.getContextValue(SESSION_ID_CONTEXT_KEY)), 3) userId = msg.getContextValue(USER_ID_CONTEXT_KEY) if userId is not None: student = self.retrieveStudentFromCacheOrDB(userId, msg, True) else: student = None session = DBSession(sessionId = msg.getContextValue(SESSION_ID_CONTEXT_KEY)) session.messageIds = [] session.hints = [] session.feedback = [] session.performance = {} session.startTime = datetime.utcnow().strftime(DATE_TIME_FORMAT) session.duration = 0 session.subtaskNumber = -1 session.id = msg.getContextValue(SESSION_ID_CONTEXT_KEY) session.task = msg.getContextValue(TASK_ID_CONTEXT_KEY) if session.task in self.taskASSISTmentsDictionary.keys(): session.task = self.taskASSISTmentsDictionary[session.task] if student is not None: student.sessionIds.append(session.id) session.students.append(student.studentId) student.save() session.save() self.sessionCache[session.id] = session return session
def studentModelCallBack(self, msg, oldMsg): logInfo("Entering Recommender.studentModelCallback", 5) #hack instrumentation student = self.recommender.retrieveStudentFromCacheOrDB( msg.getObject(), None, True) #logInfo("dbStudentRecord = {0}".format(student), 6) serializableStudent = student.toSerializable() logInfo( "student record = {0}".format( serializableStudent.saveToSerialized()), 2) # Make sure that it is the right student's score for the request recMsg = oldMsg.getContextValue(self.ORIGINAL_MESSAGE_KEY, Message()) if (msg.getVerb() == MASTERY_VERB and msg.getSpeechAct() == INFORM_ACT and msg.getObject() == recMsg.getActor()): if isinstance(recMsg.getObject(), (int, float)): numberOfRecommendations = int(recMsg.getObject()) else: numberOfRecommendations = 3 recommendedTasks = self.recommender.getRecommendedTasks( msg.getObject(), msg.getResult(), numberOfRecommendations) self.sendRecommendations(recommendedTasks, recMsg)
def addTopicToCalendar(self, topic, calendarData, startTime, endTime=None, duration=None): if startTime is None: logInfo("startTime not found, will not add task", 3) return calenderAsObject = Calendar.from_ical(calendarData.calendarData) newEvent = Event() newEvent.add('summary', topic.topicId) newEvent.add(COMMENT_KEY, "{0} = {1}".format(TOPIC_ID, topic.topicId)) startTimeAsDateTime = datetime.strptime(startTime, DATE_TIME_FORMAT) newEvent.add(START_TIME_KEY, startTimeAsDateTime) if endTime is not None: endTimeAsDateTime = datetime.strptime(endTime, DATE_TIME_FORMAT) newEvent.add('dtend', endTimeAsDateTime) elif duration is not None: newEvent.add('duration', duration) calenderAsObject.add_component(newEvent) calendarData.calendarData = calenderAsObject.to_ical() return
def processStorageRequest(self, bucket, verb, key=None, tags=None, aType=None, name=None): logInfo("No handlers for REQUEST messages available", 5)
def getAssistementsItem(self, useCachedValue=False): if not useCachedValue: logInfo("assistmentItemId={0}".format(self.assistmentsItemId), 6) if self.assistmentsItemId is not None: return DBAssistmentsItem.find_one(self.assistmentsItemId) else: return None else: return self.assistmentsItemCache
def createStudent(self, studentId, msg): logInfo('{0} could not find student with id: {1} in database. Creating new student'.format(self.serviceName, studentId), 3) studentUUID = str(uuid4()) student = DBStudent(id=studentUUID, studentId=studentId, sessionIds=[], oAuthIds={}, studentModelIds={}, kcGoals={}) student.save() self.studentCache[studentId] = student newStudentAlias = DBStudentAlias(trueId=studentUUID, alias=studentId) newStudentAlias.save() return student
def createClass(self, classId, msg): logInfo('{0} could not find class with id: {1} in database. Creating new class'.format(self.serviceName, classId), 3) classUUID = str(uuid4()) clazz = DBClass(id=classUUID, ids=[classId], name='', roles={}, students=[], kcs=[]) clazz.save() self.classCache[classId] = clazz newClassAlias = DBClasssAlias(trueId=classUUID, alias=classId) newClassAlias.save() return clazz
def findAssignmentNumber(self, task, sessions): possibleTaskNumber = -1 for session in sessions: #sessionTask = session.getTask() #logInfo("task id is {0}, and session id is {1}".format(task._taskId, session.task), 1) if task._taskId == session.task: logInfo("found session with previous task", 1) possibleTaskNumber = int(session.assignmentNumber) return possibleTaskNumber + 1
def findAssignmentNumber(self, task, sessions): possibleTaskNumber = -1 for session in sessions: #sessionTask = session.getTask() #logInfo("task id is {0}, and session id is {1}".format(task._taskId, session.task), 1) if task._taskId == session.task: logInfo("found session with previous task", 1) possibleTaskNumber = int(session.assignmentNumber); return possibleTaskNumber + 1
def addStudentModel(self, newStudentModel): logInfo("Entering DBStudent.addStudentModel", 5) if newStudentModel is None: return if newStudentModel.id is None or newStudentModel.id is '': newStudentModel.save() self.studentModelCache[newStudentModel.id] = newStudentModel if self.studentModelIds is None or isinstance(self.studentModelIds, list): self.studentModelIds = {} self.studentModelIds[newStudentModel.__class__.__name__] = newStudentModel.id self.save()
def getRecommendedTasks(self, studentId, studentModel, numberOfTasksRequested): logInfo("MAKING RECOMMENDATIONS", 1) taskMastery = list() dbtaskList = DBTask.find_all() dbassistmentItemsList = DBAssistmentsItem.find_all() for dbTask in dbtaskList: if dbTask.assistmentsItemId is not None and dbTask.assistmentsItemId is not '': for dbassistmentsItem in dbassistmentItemsList: if dbassistmentsItem.id == dbTask.assistmentsItemId: dbTask.assistmentsItemCache = dbassistmentsItem break taskList = [x.toSerializable() for x in dbtaskList] logInfo("RETRIEVED TASKS FROM DATABASE", 1) #taskList = self.validateTasks(taskList) #taskList = self.checkNovelty(studentId, taskList) for task in taskList: taskMastery.append((self.calcMaxMasteryGain(task, studentModel), task)) sortedTaskMastery = sorted(taskMastery, key=lambda taskMastery: taskMastery[0], reverse=True) #logInfo("sortedTaskMastery={0}".format(sortedTaskMastery), 6) result = sortedTaskMastery #print("RESULT: " + str(len(result))) student = self.retrieveStudentFromCacheOrDB(studentId, None, True) logInfo("retrieved student", 1) sessions = student.getSessions(False) logInfo("retrieved sessions", 1) for gain, task in result: if task._assistmentsItem is not None: task._assistmentsItem._assignmentNumber = self.findAssignmentNumber( task, sessions) # print("TASK: " + str(task)) #print(str(task._assistmentsItem)) result = [ task for gain, task in result if task._assistmentsItem is not None and task._assistmentsItem.getActiveAssignmentURL() is not None ] result = result[0:numberOfTasksRequested] #print("RESULT:" + str(result)) logInfo("GOT RESULT", 1) return result
def receiveMessage(self, msg): super(RecommenderMessaging, self).receiveMessage(msg) #depending on the content of the message react differently logInfo('Entering Recommender.receiveMessage', 5) if self.recommender.taskASSISTmentsDictionary is None: self.recommender.taskASSISTmentsDictionary = self.recommender.populateTaskAssistmentsDictionary() if (msg.getSpeechAct() == REQUEST_ACT and msg.getVerb() == RECOMMENDED_TASKS_VERB): outMsg = Message(None, MASTERY_VERB, msg.getActor(), msg.getObject(), REQUEST_ACT) #TODO: Replace with the ability to store context w/ the request in the base recommender class outMsg.setContextValue(self.ORIGINAL_MESSAGE_KEY, msg) self._makeRequest(outMsg, self.studentModelCallBack)
def addStudentModel(self, newStudentModel): logInfo("Entering DBStudent.addStudentModel", 5) if newStudentModel is None: return if newStudentModel.id is None or newStudentModel.id is '': newStudentModel.save() self.studentModelCache[newStudentModel.id] = newStudentModel if self.studentModelIds is None or isinstance(self.studentModelIds, list): self.studentModelIds = {} self.studentModelIds[ newStudentModel.__class__.__name__] = newStudentModel.id self.save()
def receiveMessage(self, msg): super(StudentModelMessaging, self).receiveMessage(msg) if self.studentModel_internal.taskASSISTmentsDictionary is None: self.studentModel_internal.taskASSISTmentsDictionary = self.studentModel_internal.populateTaskAssistmentsDictionary() if msg.getVerb() != HEARTBEAT_VERB: logInfo('{0} received message: {1}'.format(STUDENT_MODEL_SERVICE_NAME, self.messageToString(msg)), 2) if msg is not None: reply = self.routeMessage(msg) if reply is not None: logInfo('{0} is sending reply:{1}'.format(STUDENT_MODEL_SERVICE_NAME, self.messageToString(reply)), 2) self.sendMessage(reply)
def receiveMessage(self, msg): super(RecommenderMessaging, self).receiveMessage(msg) #depending on the content of the message react differently logInfo('Entering Recommender.receiveMessage', 5) if self.recommender.taskASSISTmentsDictionary is None: self.recommender.taskASSISTmentsDictionary = self.recommender.populateTaskAssistmentsDictionary( ) if (msg.getSpeechAct() == REQUEST_ACT and msg.getVerb() == RECOMMENDED_TASKS_VERB): outMsg = Message(None, MASTERY_VERB, msg.getActor(), msg.getObject(), REQUEST_ACT) #TODO: Replace with the ability to store context w/ the request in the base recommender class outMsg.setContextValue(self.ORIGINAL_MESSAGE_KEY, msg) self._makeRequest(outMsg, self.studentModelCallBack)
def retrieveTopicFromCacheOrDB(self, topicId, useCache=True): if topicId is None: return None if topicId in self.taskCache.keys() and useCache: logInfo('{0} found cached task object with id:{1}'.format(self.serviceName, topicId), 4) return self.taskCache[topicId] else: logInfo('{0} could not find cached topic object with id: {1}. Falling back to database.'.format(self.serviceName, topicId), 3) dbTopicList = DBTopic.find_by_index("topicIdIndex", topicId) if len(dbTopicList) > 0: task = dbTopicList[0] #Cache the result so we don't need to worry about looking it up again. self.taskCache[topicId] = task return task else: return None
def createNewStudentModel(self, studentId): #DBStudentAlias List studentsWithId = DBStudentAlias.find_by_index("AliasIndex", studentId) if len(studentsWithId) == 0: logInfo('failed to find student alias {0}'.format(studentId), 1) student = self.createStudent(studentId, None) return WeightedStudentModelFactory().buildStudentModel(student) for studentAlias in studentsWithId: student = DBStudent.find_one(studentAlias.trueId) if student is None: logInfo('failed to find student with Id: {0} and alias {1}'.format(studentAlias.trueId, studentAlias.alias), 1) student = self.createStudent(studentId, None) return WeightedStudentModelFactory().buildStudentModel(student) else: return WeightedStudentModelFactory().buildStudentModel(student)
def buildStudentModel(self, student): #List<DBSession> self.sessionList = student.getSessions(False) if len(self.sessionList) == 0: logInfo( 'student {0} has not started any sessions. cannot build student model' .format(student.studentId), 2) return None #Dictionary<string, tuple(float totalScore, int numberOfEntries)> kcScoreTotals = {} logInfo( 'building student model for student {0}'.format(student.studentId), 3) for session in self.sessionList: #sanity check to make sure the student took part in the session. if student.studentId not in session.performance: logInfo( 'student {0} was attached to session {1}, but no kc score was ever recorded' .format(student.studentId, session.sessionId), 2) else: studentPerformance = session.performance[student.studentId] for kc in studentPerformance.keys(): kcSessionValue = studentPerformance[kc] kcScoreTotal = None if kc not in kcScoreTotals: kcScoreTotal = (kcSessionValue, 1) else: oldKCScoreTotal = kcScoreTotals[kc] kcScoreTotal = (oldKCScoreTotal[0] + kcSessionValue, oldKCScoreTotal[1] + 1) kcScoreTotals[kc] = kcScoreTotal result = DBStudentModel() result.studentId = student.studentId result.kcMastery = {} #note it should not be possible to get a divide by zero error here since the denominator is always > 1 for kc in kcScoreTotals.keys(): kcScoreTotal = kcScoreTotals[kc] result.kcMastery[kc] = kcScoreTotal[0] / kcScoreTotal[1] logInfo( 'built student model for student {0}'.format(student.studentId), 3) student.addStudentModel(result) return result
def createNewStudentModel(self, studentId): #DBStudentAlias List studentsWithId = DBStudentAlias.find_by_index("AliasIndex", studentId) if len(studentsWithId) == 0: logInfo('failed to find student alias {0}'.format(studentId), 1) student = self.createStudent(studentId, None) return WeightedStudentModelFactory().buildStudentModel(student) for studentAlias in studentsWithId: student = DBStudent.find_one(studentAlias.trueId) if student is None: logInfo( 'failed to find student with Id: {0} and alias {1}'.format( studentAlias.trueId, studentAlias.alias), 1) student = self.createStudent(studentId, None) return WeightedStudentModelFactory().buildStudentModel(student) else: return WeightedStudentModelFactory().buildStudentModel(student)
def studentModelCallBack(self, msg, oldMsg): logInfo("Entering Recommender.studentModelCallback", 5) #hack instrumentation student = self.recommender.retrieveStudentFromCacheOrDB(msg.getObject(), None, True) #logInfo("dbStudentRecord = {0}".format(student), 6) serializableStudent = student.toSerializable() logInfo("student record = {0}".format(serializableStudent.saveToSerialized()), 2) # Make sure that it is the right student's score for the request recMsg = oldMsg.getContextValue(self.ORIGINAL_MESSAGE_KEY, Message()) if (msg.getVerb() == MASTERY_VERB and msg.getSpeechAct() == INFORM_ACT and msg.getObject() == recMsg.getActor()): if isinstance(recMsg.getObject(), (int, float)): numberOfRecommendations = int(recMsg.getObject()) else: numberOfRecommendations = 3 recommendedTasks = self.recommender.getRecommendedTasks(msg.getObject(), msg.getResult(), numberOfRecommendations) self.sendRecommendations(recommendedTasks, recMsg)
def create(self, serializableDBTask = None): logInfo("found DBTask constructor", 5) if serializableDBTask is not None: self.taskId = serializableDBTask._taskId self.system = serializableDBTask._system self.ids = serializableDBTask._aliasIds self.subtasks = serializableDBTask._subtasks self.name = serializableDBTask._name self.displayName = serializableDBTask._displayName self.kcs = serializableDBTask._kcs self.baseURL = serializableDBTask._baseURL if serializableDBTask._assistmentsItem is not None: self.assistmentsItemCache = DBSerializable.convert(serializableDBTask._assistmentsItem) self.assistmentsItemId = serializableDBTask._assistmentsItem.getId() else: self.assistmentsItemCache = None self.assistmentsItemId = None self.description = serializableDBTask._description self.canBeRecommendedIndividually = serializableDBTask._canBeRecommendedIndividually return self
def receiveMessage(self, msg): #depending on the content of the message react differently #logInfo('Entering CSVReader.receiveMessage', 5) reply = None #Only considering if msg.getSpeechAct() == INFORM_ACT: if msg.getVerb() == ELECTRONIX_TUTOR_TASK_UPLOAD_VERB: logInfo( '{0} is processing a {1},{2} message'.format( CSV_READER_SERVICE_NAME, ELECTRONIX_TUTOR_TASK_UPLOAD_VERB, INFORM_ACT), 4) csvString = msg.getResult() taskList = self.processCSVFile(csvString) print("STORAGE SERVICE NAME: %s" % (STORAGE_SERVICE_NAME)) reply = Message(STORAGE_SERVICE_NAME, VALUE_VERB, TASKS_OBJECT, taskList) if msg.getSpeechAct() == REQUEST_ACT: if msg.getVerb() == ELECTRONIX_TUTOR_TASK_UPLOAD_VERB: dbtaskList = DBTask.find_all() dbassistmentItemsList = DBAssistmentsItem.find_all() for dbTask in dbtaskList: if dbTask.assistmentsItemId is not None and dbTask.assistmentsItemId is not '': for dbassistmentsItem in dbassistmentItemsList: if dbassistmentsItem.id == dbTask.assistmentsItemId: dbTask.assistmentsItemCache = dbassistmentsItem break taskList = [x.toSerializable() for x in dbtaskList] reply = Message(CSV_READER_SERVICE_NAME, ELECTRONIX_TUTOR_TASK_UPLOAD_VERB, None, taskList, INFORM_ACT, msg.getContext()) if reply is not None: logInfo( '{0} is broadcasting a {1}, {2} message'.format( CSV_READER_SERVICE_NAME, INFORM_ACT, VALUE_VERB), 4) self.sendMessage(reply)
def getRecommendedTasks(self, studentId, studentModel, numberOfTasksRequested): print("MAKING RECOMMENDATIONS") taskMastery = list() dbtaskList = DBTask.find_all() dbassistmentItemsList = DBAssistmentsItem.find_all() for dbTask in dbtaskList: if dbTask.assistmentsItemId is not None and dbTask.assistmentsItemId is not '': for dbassistmentsItem in dbassistmentItemsList: if dbassistmentsItem.id == dbTask.assistmentsItemId: dbTask.assistmentsItemCache = dbassistmentsItem break taskList = [x.toSerializable() for x in dbtaskList] print("RETRIEVED TASKS FROM DATABASE") #taskList = self.validateTasks(taskList) #taskList = self.checkNovelty(studentId, taskList) for task in taskList: taskMastery.append((self.calcMaxMasteryGain(task, studentModel), task)) sortedTaskMastery = sorted(taskMastery, key=lambda taskMastery : taskMastery[0], reverse=True) #logInfo("sortedTaskMastery={0}".format(sortedTaskMastery), 6) result = sortedTaskMastery #print("RESULT: " + str(len(result))) student = self.retrieveStudentFromCacheOrDB(studentId, None, True) logInfo("retrieved student", 1) sessions = student.getSessions(False) logInfo("retrieved sessions", 1) for gain, task in result: if task._assistmentsItem is not None: task._assistmentsItem._assignmentNumber = self.findAssignmentNumber(task, sessions) # print("TASK: " + str(task)) #print(str(task._assistmentsItem)) result = [task for gain, task in result if task._assistmentsItem is not None and task._assistmentsItem.getActiveAssignmentURL() is not None] result = result[0:numberOfTasksRequested] #print("RESULT:" + str(result)) return result
def updateStateRLAAR(self, msg): try: #if message is transcript update if TRANSCRIPT_UPDATE in msg.getVerb(): logInfo( '{0} received AAR item update message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) item = int(msg.getContextValue(ORDER)) max_key = int(max(AAR_item.keys(), key=int) if AAR_item else 0) if max_key == -1 or None: max_key = 0 if item > max_key + 1: diff = item - (max_key + 1) for i in range(diff): missed_item = max_key + 1 + i self.rLService_random.updateAARItem(missed_item) print(item) if msg.getResult() == CORRECT: AAR_item[item] = SKIP else: self.rLService_random.updateNonCorrectAARItem(item) print(AAR_item) #if message informs the start of AAR elif BEGIN_AAR in msg.getVerb(): logInfo( '{0} received AAR item final update message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) AAR_item['-1'] = DONE except: logInfo( '{0} received RL AAR update message exception: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2)
def updateStateRLAAR(self,msg): try: #if message is transcript update if TRANSCRIPT_UPDATE in msg.getVerb(): logInfo('{0} received AAR item update message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) item = int(msg.getContextValue(ORDER)) max_key = int(max(AAR_item.keys(), key=int) if AAR_item else 0) if max_key == -1 or None: max_key = 0 if item > max_key+1: diff = item - (max_key+1) for i in range(diff): missed_item = max_key+1+i self.rLService_random.updateAARItem(missed_item) print(item) if msg.getResult() == CORRECT: AAR_item[item] = SKIP else: self.rLService_random.updateNonCorrectAARItem(item) print(AAR_item) #if message informs the start of AAR elif BEGIN_AAR in msg.getVerb(): logInfo('{0} received AAR item final update message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) AAR_item['-1'] = DONE except: logInfo('{0} received RL AAR update message exception: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2)
def receiveMessage(self, msg): super(StudentModelMessaging, self).receiveMessage(msg) if self.studentModel_internal.taskASSISTmentsDictionary is None: self.studentModel_internal.taskASSISTmentsDictionary = self.studentModel_internal.populateTaskAssistmentsDictionary( ) if msg.getVerb() != HEARTBEAT_VERB: logInfo( '{0} received message: {1}'.format(STUDENT_MODEL_SERVICE_NAME, self.messageToString(msg)), 2) if msg is not None: reply = self.routeMessage(msg) if reply is not None: logInfo( '{0} is sending reply:{1}'.format(STUDENT_MODEL_SERVICE_NAME, self.messageToString(reply)), 2) self.sendMessage(reply)
def create(self, serializableDBTask=None): logInfo("found DBTask constructor", 5) if serializableDBTask is not None: self.taskId = serializableDBTask._taskId self.system = serializableDBTask._system self.ids = serializableDBTask._aliasIds self.subtasks = serializableDBTask._subtasks self.name = serializableDBTask._name self.displayName = serializableDBTask._displayName self.kcs = serializableDBTask._kcs self.baseURL = serializableDBTask._baseURL if serializableDBTask._assistmentsItem is not None: self.assistmentsItemCache = DBSerializable.convert( serializableDBTask._assistmentsItem) self.assistmentsItemId = serializableDBTask._assistmentsItem.getId( ) else: self.assistmentsItemCache = None self.assistmentsItemId = None self.description = serializableDBTask._description self.canBeRecommendedIndividually = serializableDBTask._canBeRecommendedIndividually return self
def findAssignmentNumber(self, task, sessions): possibleTaskNumber = -1 for session in sessions: #sessionTask = session.getTask() #logInfo("task id is {0}, and session id is {1}".format(task._taskId, session.task), 1) if task._taskId == session.task: logInfo("found session with previous task", 1) if session.assignmentNumber is not None: logInfo( "session.assignmentNumber = {0}".format( session.assignmentNumber), 5) try: possibleTaskNumber = int(session.assignmentNumber) except: logWarning( "Failed to Find session.assignmentNumber for | {0}" .format(session.task)) possibleTaskNumber = 0 else: possibleTaskNumber = 0 return possibleTaskNumber + 1
def addTopicToCalendar(self, topic, calendarData, startTime, endTime=None, duration=None): if startTime is None: logInfo("startTime not found, will not add task", 3) return calenderAsObject = Calendar.from_ical(calendarData.calendarData) newEvent = Event() newEvent.add("summary", topic.topicId) newEvent.add(COMMENT_KEY, "{0} = {1}".format(TOPIC_ID, topic.topicId)) startTimeAsDateTime = datetime.strptime(startTime, DATE_TIME_FORMAT) newEvent.add(START_TIME_KEY, startTimeAsDateTime) if endTime is not None: endTimeAsDateTime = datetime.strptime(endTime, DATE_TIME_FORMAT) newEvent.add("dtend", endTimeAsDateTime) elif duration is not None: newEvent.add("duration", duration) calenderAsObject.add_component(newEvent) calendarData.calendarData = calenderAsObject.to_ical() return
def getCalendarFromOwnerId(self, ownerId=None, useCache=True): if ownerId is None: logWarning("NO OWNER ID WAS GIVEN WHEN ATTEMPTING TO LOOK UP CALENDAR") return None if useCache: result = self.calendarCache.get(ownerId, None) if result is not None: return result; foundCalendars = DBCalendarData.find_by_index("ownerIdIndex", []) calendarData = None if len(foundCalendars) == 0: logInfo("No calendar found, creating a new calendar for owner:{0}".format(ownerId), 1) calendarData = DBCalendarData() calendarData.setCalendarData(ownerId) elif len(foundCalendars) == 1: calendarData = foundCalendars[0] elif len(foundCalendars) > 1: logWarning("{0} owns more than a single calendar. Database may be corrupted. Defaulting to the first value".format(ownerId)) calendarData = foundCalendars[0] self.calendarCache[ownerId] = calendarData return calendarData
def processStorageInform(self, bucket, verb, key=None, value=None, tags=None, aType=None, allowCreate=None, name=None, description=None, dataType=None): if verb == self.VALUE_VERB: logWarning("IS SETTING", value) if isinstance(value, Serializable): logWarning("IS SERIALIZABLE") if key is None: key = value.getId() elif key != value.getId(): logWarning('BAD KEY for Storage (%s != %s)'%(key, value.getId())) return False if isinstance(value, NamedSerializable): if name is None: name = value.getName() elif name != value.getName(): logWarning('BAD NAME for Storage(%s != %s)'%(name, value.getName())) return False #NOTE we are assuming that the value class and dbValue class have the toDB and saveToDB functions respectively. #If they do not have them they must be implemented or the system will not save the data. try: if isinstance(value, list): for valueObject in value: logInfo("saving task {0} to database".format(valueObject._name), 4) dbValue = DBSerializable.convert(valueObject) dbValue.saveToDB() except NotImplementedError: logInfo('failed to serialize object', 1) dbValue = JSONtoDBSerializable(value) dbValue.saveToDB() return True #GLUDB does not currently allow for deletion of items so this should always return false elif verb == self.VOID_VERB: return False
def buildStudentModel(self, student): #List<DBSession> self.sessionList = student.getSessions(False) if len(self.sessionList) == 0: logInfo('student {0} has not started any sessions. cannot build student model'.format(student.studentId), 2) return None #Dictionary<string, tuple(float totalScore, int numberOfEntries)> kcScoreTotals = {} logInfo('building student model for student {0}'.format(student.studentId), 3) for session in self.sessionList: #sanity check to make sure the student took part in the session. if student.studentId not in session.performance: logInfo('student {0} was attached to session {1}, but no kc score was ever recorded'.format(student.studentId, session.sessionId), 2) else: studentPerformance = session.performance[student.studentId] for kc in studentPerformance.keys(): kcSessionValue = studentPerformance[kc] kcScoreTotal = None if kc not in kcScoreTotals: kcScoreTotal = (kcSessionValue, 1) else: oldKCScoreTotal = kcScoreTotals[kc] kcScoreTotal = (oldKCScoreTotal[0] + kcSessionValue, oldKCScoreTotal[1] + 1) kcScoreTotals[kc] = kcScoreTotal result = DBStudentModel() result.studentId = student.studentId result.kcMastery = {} #note it should not be possible to get a divide by zero error here since the denominator is always > 1 for kc in kcScoreTotals.keys(): kcScoreTotal = kcScoreTotals[kc] result.kcMastery[kc] = kcScoreTotal[0] / kcScoreTotal[1] logInfo('built student model for student {0}'.format(student.studentId), 3) student.addStudentModel(result) return result
def retrieveSessionFromCacheOrDB(self, sessionId, useCache=True): if sessionId is None: return None if sessionId in self.sessionCache.keys() and useCache: logInfo('{0} found cached session object with id:{1}'.format(self.serviceName, sessionId), 4) return self.sessionCache[sessionId] logInfo('{0} could not find cached session object with id: {1}. Falling back to database.'.format(self.serviceName, sessionId), 3) session = DBSession.find_one(sessionId) if session is not None: logInfo('{0} found session {1}. Storing in Cache'.format(self.serviceName, session.sessionId), 5) self.sessionCache[session.id] = session return session
def checkNovelty(self, studentId, taskList): student = self.retrieveStudentFromCacheOrDB(studentId, None, True) logInfo("retrievedStudent In check novelty", 1) tasksToRemove = [] if len(student.sessionIds) > 0: sessions = student.getSessions(False) logInfo("got sessions In check Novelty", 1) for task in taskList: for session in sessions: #add more conditions to allow us to recommend the same task twice #logInfo("getting Task for session", 1) #sessionTask = session.getTask() #logInfo("gotTask", 1) if session.task is not None and task._taskId == session.task: tasksToRemove.append(task) for taskToRemove in tasksToRemove: taskList.remove(taskToRemove) logInfo("checked novelty", 1) return taskList
def retrieveStudentFromCacheOrDB(self, studentId, msg, useCache=True): logInfo("Entering retrieveStudentFromCacheOrDB", 5) student = self.studentCache.get(studentId) if student is not None and useCache: logInfo('{0} found student object with id:{1}'.format(self.serviceName, studentId), 4) return student else: logInfo('{0} could not find cached student object with id: {1}. Falling back to database.'.format(self.serviceName, studentId), 3) studentAliasList = DBStudentAlias.find_by_index("AliasIndex", studentId) if len(studentAliasList) > 0: #there should only be one object returned, should put it a log statement if that isn't correct. for studentAlias in studentAliasList: student = studentAlias.getStudent() if student is None: student = self.createStudent(studentId, msg) #Cache the result so we don't need to worry about looking it up again. self.studentCache[studentId] = student return student
def retrieveClassFromCacheOrDB(self, classId, msg, useCache=True): logInfo("Entering retrieveClassFromCacheOrDB with arguments {0}".format(classId), 5) if classId is None or classId == '': return None clazz = self.studentCache.get(classId) if clazz is not None and useCache: logInfo('{0} found classroom object with id:{1}'.format(self.serviceName, clazz), 4) return clazz else: logInfo('{0} could not find cached classroom object with id: {1}. Falling back to database.'.format(self.serviceName, classId), 3) classAliasList = DBClasssAlias.find_by_index("AliasIndex", classId) if len(classAliasList) > 0: #there should only be one object returned, should put it a log statement if that isn't correct. for classAlias in classAliasList: clazz = classAlias.getStudent() if clazz is None: clazz = self.createClass(classId, msg) #Cache the result so we don't need to worry about looking it up again. self.classCache[classId] = clazz return clazz
def retrieveTaskFromCacheOrDB(self, taskId, useCache=True): if taskId is None: return None if taskId in self.taskCache.keys() and useCache: logInfo('{0} found cached task object with id:{1}'.format(self.serviceName, taskId), 4) return self.taskCache[taskId] else: logInfo('{0} could not find cached task object with id: {1}. Falling back to database.'.format(self.serviceName, taskId), 3) dbTaskList = DBTask.find_by_index("taskIdIndex", taskId) task = None if len(dbTaskList) > 0: task = dbTaskList[0] else: logInfo('{0} could not find cached task object with id: {1}. attempting to find by ASSISTments item Id.'.format(self.serviceName, taskId), 3) if self.taskASSISTmentsDictionary is not None and taskId in self.taskASSISTmentsDictionary.keys(): dbTaskList = DBTask.find_by_index("taskIdIndex", self.taskASSISTmentsDictionary[taskId]) if len(dbTaskList) > 0: task = dbTaskList[0] #Cache the result so we don't need to worry about looking it up again. self.taskCache[taskId] = task return task
def receiveMessage(self, msg): super(RLServiceMessaging, self).receiveMessage(msg) #Check specific messages for AAR and Coach #if message asks for the next agenda item in AAR if GET_NEXT_AGENDA_ITEM in msg.getVerb(): #if AAR Item list reply as done if not AAR_item: print('Empty AAR') item = -1 action = DONE else: #loops through dictionary for item in list(AAR_item.keys()): action = AAR_item[item] #if skip don't reply if action == SKIP: print('item skipped') del AAR_item[item] else: print('item ' + str(item) + ' action ' + action) #delete item and break del AAR_item[item] break #if SKIPs remain, its the end of the item list if action == SKIP: item = -1 action = DONE #send message reply_msg = self._createRequestReply(msg) reply_msg.setResult(action) reply_msg.setVerb(PERFORM_ACTION) reply_msg.setObject(item) if reply_msg is not None: logInfo( '{0} is sending reply for AAR agenda item:{1}'.format( RL_SERVICE_NAME, self.messageToString(reply_msg)), 2) self.sendMessage(reply_msg) #if Elite asks for coaching action elif REQUEST_COACHING_ACTIONS in msg.getVerb(): logInfo( '{0} received request coaching action message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) #for random RL if self.experimentCondition == "A": action = self.rLService_random.getTopAction() else: #for trained policy based RL try: action = self.rLService_feature.getTopAction() except: action = DO_NOTHING #send message reply_msg = self._createRequestReply(msg) reply_msg.setResult(action) reply_msg.setVerb(COACHING_ACTIONS) if reply_msg is not None: logInfo( '{0} is sending reply for coaching request:{1}'.format( RL_SERVICE_NAME, self.messageToString(reply_msg)), 2) self.sendMessage(reply_msg) #consider message for state update - can also reuse TRANSCRIPT_UPDATE for correctness ??? else: logInfo( '{0} received state update message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) #update RL AAR state based on the message self.rLService_internal.updateStateRLAAR(msg) #update RL coach state based on the message self.rLService_internal.updateStateRLCoach(msg)
def receiveMessage(self, msg): super(RLServiceMessaging, self).receiveMessage(msg) #Check specific messages for AAR and Coach #if message asks for the next agenda item in AAR if GET_NEXT_AGENDA_ITEM in msg.getVerb(): #if AAR Item list reply as done if not AAR_item: print('Empty AAR') item = -1 action = DONE else: #loops through dictionary for item in list(AAR_item.keys()): action = AAR_item[item] #if skip don't reply if action == SKIP: print('item skipped') del AAR_item[item] else: print('item ' + str(item) +' action ' + action) #delete item and break del AAR_item[item] break #if SKIPs remain, its the end of the item list if action == SKIP: item = -1 action = DONE #send message reply_msg = self._createRequestReply(msg) reply_msg.setResult(action) reply_msg.setVerb(PERFORM_ACTION) reply_msg.setObject(item) if reply_msg is not None: logInfo('{0} is sending reply for AAR agenda item:{1}'.format(RL_SERVICE_NAME, self.messageToString(reply_msg)), 2) self.sendMessage(reply_msg) #if Elite asks for coaching action elif REQUEST_COACHING_ACTIONS in msg.getVerb(): logInfo('{0} received request coaching action message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) #for random RL if self.experimentCondition=="A": action = self.rLService_random.getTopAction() else: #for trained policy based RL try: action = self.rLService_feature.getTopAction() except: action = DO_NOTHING #send message reply_msg = self._createRequestReply(msg) reply_msg.setResult(action) reply_msg.setVerb(COACHING_ACTIONS) if reply_msg is not None: logInfo('{0} is sending reply for coaching request:{1}'.format(RL_SERVICE_NAME, self.messageToString(reply_msg)), 2) self.sendMessage(reply_msg) #consider message for state update - can also reuse TRANSCRIPT_UPDATE for correctness ??? else: logInfo('{0} received state update message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) #update RL AAR state based on the message self.rLService_internal.updateStateRLAAR(msg) #update RL coach state based on the message self.rLService_internal.updateStateRLCoach(msg)
def saveToDB(self): existingTasksWithSameName = DBTask.find_by_index( 'nameIndex', self.name) existingTask = None logInfo( "assistmentsItemcacheValue2 = {0}".format( self.assistmentsItemCache), 6) for possibleExistingTask in existingTasksWithSameName: if self.ids == possibleExistingTask.ids: existingTask = possibleExistingTask if existingTask is None: logInfo("task with name {0} does not yet exist".format(self.name), 3) if self.assistmentsItemCache: self.assistmentsItemCache.saveToDB() self.assistmentsItemId = self.assistmentsItemCache.id logInfo("assistmentsItemId = {0}".format(self.assistmentsItemId), 6) logInfo( "assistmentsItemcacheValue4 = {0}".format( self.assistmentsItemCache), 6) self.save() for kc in self.kcs: #TODO: figure out what tod do with these alias = DBKCTaskAssociations() alias.kc = kc alias.taskId = self.id alias.save() else: logInfo( "task with name {0} already exists, overwriting".format( self.name), 3) existingTask.name = self.name existingTask.displayName = self.displayName existingTask.ids = self.ids existingTask.kcs = self.kcs existingTask.baseURL = self.baseURL existingTask.description = self.description existingTask.canBeRecommendedIndividually = self.canBeRecommendedIndividually self.assistmentsItemCache.id = existingTask.assistmentsItemId existingTask.assistmentsItemCache = self.assistmentsItemCache if existingTask.assistmentsItemCache: existingTask.assistmentsItemCache.saveToDB() existingTask.assistmentsItemId = existingTask.assistmentsItemCache.id logInfo( "assistmentsItemcacheValue3 = {0}".format( existingTask.assistmentsItemCache), 6) logInfo( "assistmentsItemId = {0}".format( existingTask.assistmentsItemId), 6) existingTask.save() return self.id
def routeMessage(self, msg): #depending on the content of the message react differently #logInfo('Entering StudentModelMessaging.routeMessage', 5) result = None #Only considering if msg.getSpeechAct() == INFORM_ACT: if msg.getVerb() == KC_SCORE_VERB: logInfo('{0} is processing a {1},{2} message'.format(STUDENT_MODEL_SERVICE_NAME, KC_SCORE_VERB, INFORM_ACT), 4) self.studentModel_internal.informKCScoreVerb(msg) logInfo('{0} finished processing {1},{2}'.format(STUDENT_MODEL_SERVICE_NAME, KC_SCORE_VERB, INFORM_ACT), 4) elif msg.getVerb() == TASK_HINT_VERB: logInfo('{0} is processing a {1},{2} message'.format(STUDENT_MODEL_SERVICE_NAME, TASK_HINT_VERB, INFORM_ACT), 4) self.studentModel_internal.informTaskHintVerb(msg) logInfo('{0} finished processing {1},{2}'.format(STUDENT_MODEL_SERVICE_NAME, TASK_HINT_VERB, INFORM_ACT), 4) elif msg.getVerb() == TASK_FEEDBACK_VERB: logInfo('{0} is processing a {1},{2} message'.format(STUDENT_MODEL_SERVICE_NAME, TASK_FEEDBACK_VERB, INFORM_ACT), 4) self.studentModel_internal.informTaskFeedBackVerb(msg) logInfo('{0} finished processing {1}, {2}'.format(STUDENT_MODEL_SERVICE_NAME, TASK_FEEDBACK_VERB, INFORM_ACT), 4) elif msg.getVerb() == COMPLETED_VERB: logInfo('{0} is processing a {1},{2} message'.format(STUDENT_MODEL_SERVICE_NAME, COMPLETED_VERB, INFORM_ACT), 4) self.studentModel_internal.informCompleteVerb(msg) logInfo('{0} finished processing {1}, {2}'.format(STUDENT_MODEL_SERVICE_NAME, COMPLETED_VERB, INFORM_ACT), 4) elif msg.getSpeechAct() == REQUEST_ACT: print("REQUEST") if msg.getVerb() == LEARNER_SESSIONS_VERB: student = self.studentModel_internal.getStudent(msg) result = self._createRequestReply(msg) result.setActor(STUDENT_MODEL_SERVICE_NAME) result.setVerb(LEARNER_SESSIONS_VERB) result.setObject(msg.getObject()) result.setResult(student) result.setSpeechAct(INFORM_ACT) #I'm going to assume the that the student id is the object, but that may not be the case if msg.getVerb() == MASTERY_VERB: logInfo('{0} is processing a {1}, {2} message'.format(STUDENT_MODEL_SERVICE_NAME, MASTERY_VERB, REQUEST_ACT), 4) newStudentModel = self.studentModel_internal.createNewStudentModel(msg.getObject()) result = self._createRequestReply(msg) result.setActor(STUDENT_MODEL_SERVICE_NAME) result.setVerb(MASTERY_VERB) result.setSpeechAct(INFORM_ACT) result.setObject(msg.getObject()) if newStudentModel is not None: # This is a hack: need to debug why this is not producing the right serializable. #result.setResult(newStudentModel.toSerializable()) result.setResult(newStudentModel.kcMastery) else: result.setResult({}) logInfo('{0} finished processing {1},{2}'.format(STUDENT_MODEL_SERVICE_NAME, MASTERY_VERB, REQUEST_ACT), 4) return result
def processCSVFile(self, csvString): #List of strings dictLines = csv.DictReader(io.StringIO(csvString)) lines = [a for a in dictLines] relatedTasks = dict() #list of tasks result = [] for row in lines: # Extract Row Data systemId = row.get(SYSTEM_COL_NAME, '') taskId = row.get(TASK_ID_COL_NAME, '') taskDisplayName = row.get(TASK_DISPLAY_COL_NAME, '') description = row.get(DESCRIPTION_COL_NAME, '') baseURL = row.get(BASE_URL_COL_NAME, '') assistmentsItemId = row.get(ASSISTMENTS_PROB_ID_COL_NAME, '') assistmentsSetId = row.get(ASSISTMENTS_SET_ID_COL_NAME, '') assistmentsSetName = row.get(ASSISTMENTS_SET_NAME_COL_NAME, '') kcCell = row.get(KC_SET_COL_NAME, '') isEnabled = True if row.get(ENABLED_COL_NAME, 'True') == 'FALSE': isEnabled = False if isEnabled and (self.hasCellData(taskId) or self.hasCellData(taskDisplayName)): # Create the Task # logInfo('{0} is constructing the next serializable task object'.format(CSV_READER_SERVICE_NAME), 5) task = LearningTask() task._aliasIds = [] task._system = systemId # logInfo('{0} is extracting the knowledge components'.format(CSV_READER_SERVICE_NAME), 5) task._kcs = [a for a in kcCell.split(self.PIPE_DELIMITER) if a != ''] task._taskId = taskId task._name = taskDisplayName if not self.hasCellData(taskDisplayName): task._name = task._taskId elif not self.hasCellData(taskId): task._taskId = taskId task._displayName = taskDisplayName if self.hasCellData(description): task._description = description else: task._description = task._name task._aliasIds.append(taskId) task._baseURL = baseURL #if there is an assismentsItem associated with this task if self.hasCellData(assistmentsItemId): assistmentsItem = SerializableAssistmentsItem() assistmentsItem._itemId = assistmentsItemId assistmentsItem._problemSetId = assistmentsSetId assistmentsItem._problemSetName = assistmentsSetName assistmentsItem._assignments = [] logInfo('{0} is checking for assistments data'.format(CSV_READER_SERVICE_NAME), 5) for colName in ASSISTMENTS_ASSIGN_COL_NAMES: colData = row.get(colName, '') if self.hasCellData(colData): assistmentsItem._assignments.append(colData) task._assistmentsItem = assistmentsItem else: task._assistmentsItem = None #this could cause performance trouble so only use this log if you need to. #logInfo('{0} constructed task: {1}'.format(CSV_READER_SERVICE_NAME, serializeObject(task)), 5) # logInfo('{0} constructed task with name: {1}'.format(CSV_READER_SERVICE_NAME, task._name), 5) if isEnabled: result.append(task) #make additional tasks to represent combined tasks if (task._assistmentsItem): if (task._assistmentsItem._problemSetId not in relatedTasks): relatedTasks[task._assistmentsItem._problemSetId] = [] relatedTasks[task._assistmentsItem._problemSetId].append(task) for key in relatedTasks.keys(): relatedTaskList = relatedTasks[key] if len(relatedTaskList) > 1: collectedTask = LearningTask() collectedTask._ids = [] #collectedTask._ids.append()#What's going on here? kcSet = set() assignmentSet = set() collectedAssistmentsItem = SerializableAssistmentsItem() for relatedTask in relatedTaskList: relatedTask._canBeRecommendedIndividually = False # Subtask ids instead of ids field collectedTask._subtasks.append(relatedTask._taskId) if len(collectedTask._ids) == 0: collectedTask._ids.append(relatedTask._taskId) else: collectedTask._ids[0] += "~" + relatedTask._taskId if not collectedTask._name: collectedTask._name = relatedTask._name if not collectedTask._baseURL: collectedTask._baseURL = relatedTask._baseURL if not collectedTask._description: collectedTask._description = relatedTask._description if not collectedAssistmentsItem._itemId: collectedAssistmentsItem._itemId = relatedTask._assistmentsItem._itemId if not collectedAssistmentsItem._problemSetId: collectedAssistmentsItem._problemSetId = relatedTask._assistmentsItem._problemSetId if not collectedAssistmentsItem._problemSetName: collectedAssistmentsItem._problemSetName = relatedTask._assistmentsItem._problemSetName # Add all the data for kc in relatedTask._kcs: kcSet.add(kc) if relatedTask._assistmentsItem is not None: for assignment in relatedTask._assistmentsItem._assignments: assignmentSet.add(assignment) collectedTask._kcs = list(kcSet) # This is the complete set accumulated from all subtasks collectedAssistmentsItem._assignments = list(assignmentSet)# The assignments inside of this should be the set of all non-duplicate, non-empty ASSISTments assignments from the subtasks collectedTask._assistmentsItem = collectedAssistmentsItem result.append(collectedTask) logInfo('Exiting CSVReader.processCSVFile', 4) return result
def updateStateRLCoach(self, msg): #state update on relevant messages try: #update scenario if BEGIN_AAR in msg.getVerb(): logInfo( '{0} received scenario update message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) #set previous values tutoring_state[SCENARIO_NUMBER] = 2 tutoring_state[SCORE_PREV] = tutoring_state[SCORE] tutoring_state[NUMBER_OF_RESPONSE_PREV] = tutoring_state[ NUMBER_OF_RESPONSE] tutoring_state[NUMBER_OF_CORRECT_PREV] = tutoring_state[ NUMBER_OF_CORRECT] tutoring_state[NUMBER_OF_MIXED_PREV] = tutoring_state[ NUMBER_OF_MIXED] tutoring_state[NUMBER_OF_INCORRECT_PREV] = tutoring_state[ NUMBER_OF_INCORRECT] tutoring_state[AVG_RESPONSE_TIME_PREV] = tutoring_state[ AVG_RESPONSE_TIME] tutoring_state[ AVG_RESPONSE_TIME_CORRECT_PREV] = tutoring_state[ AVG_RESPONSE_TIME_CORRECT] tutoring_state[AVG_RESPONSE_TIME_MIXED_PREV] = tutoring_state[ AVG_RESPONSE_TIME_MIXED] tutoring_state[ AVG_RESPONSE_TIME_INCORRECT_PREV] = tutoring_state[ AVG_RESPONSE_TIME_INCORRECT] #reset current values tutoring_state[QUALITY_ANSWER_LAST_LAST] = 0 tutoring_state[QUALITY_ANSWER_LAST] = 0 tutoring_state[QUALITY_ANSWER] = 0 tutoring_state[SCORE] = 0 tutoring_state[SEEN_BEFORE] = 0 tutoring_state[QUALITY_PREV_IF_SEEN] = 0 tutoring_state[NUMBER_OF_RESPONSE] = 0 tutoring_state[NUMBER_OF_CORRECT] = 0 tutoring_state[NUMBER_OF_INCORRECT] = 0 tutoring_state[NUMBER_OF_MIXED] = 0 tutoring_state[RESPONSE_TIME] = 0 tutoring_state[RESPONSE_TIME_LAST] = 0 tutoring_state[RESPONSE_TIME_LAST_LAST] = 0 tutoring_state[AVG_RESPONSE_TIME] = 0 tutoring_state[AVG_RESPONSE_TIME_CORRECT] = 0 tutoring_state[AVG_RESPONSE_TIME_INCORRECT] = 0 tutoring_state[AVG_RESPONSE_TIME_MIXED] = 0 #recent locals for current self.num_response = None self.num_correct_response = None self.num_incorrect_response = None self.num_mixed_response = None self.start = None self.end = None self.time_taken = None self.time_correct = None self.time_mixed = None self.time_incorrect = None #get Gender elif REGISTER_USER_INFO in msg.getVerb(): logInfo( '{0} received gender update message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) gend = msg.getObject() if gend == FEMALE: tutoring_state[GENDER] = 2 elif gend == MALE: tutoring_state[GENDER] = 1 #update response time #verb should be GameLog, the object should be PracticeEnvironment and the result should be RandomizedChoices if msg.getVerb() == GAME_LOG and msg.getObject( ) == PRACTICE_ENVIRONMENT and msg.getResult( ) == RANDOMIZED_CHOICES: logInfo( '{0} received start timestamp update message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) self.start = msg.getTimestamp() print("start = ", self.start) #once the participant answers elif TRANSCRIPT_UPDATE in msg.getVerb(): logInfo( '{0} received transcript update message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) #store unique ID of node if tutoring_state[SCENARIO_NUMBER] == 1: logInfo( '{0} received question store message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) node_id = msg.getContextValue(NODE_ID_CONTEXT_KEY) node = [ node_id, 0 ] #quality null - will be updated when checked for correctness self.questions.append(node) #check if Chen's Utterances stored before if tutoring_state[SCENARIO_NUMBER] == 2: logInfo( '{0} received if seen before message: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) node_id = msg.getContextValue(NODE_ID_CONTEXT_KEY) for question in self.questions: if question[0] == node_id: tutoring_state[SEEN_BEFORE] = 1 tutoring_state[QUALITY_PREV_IF_SEEN] = question[1] break else: tutoring_state[SEEN_BEFORE] = 0 tutoring_state[QUALITY_PREV_IF_SEEN] = 0 print(self.start) #update lasts tutoring_state[QUALITY_ANSWER_LAST_LAST] = tutoring_state[ QUALITY_ANSWER_LAST] tutoring_state[QUALITY_ANSWER_LAST] = tutoring_state[ QUALITY_ANSWER] tutoring_state[RESPONSE_TIME_LAST_LAST] = tutoring_state[ RESPONSE_TIME_LAST] tutoring_state[RESPONSE_TIME_LAST] = tutoring_state[ RESPONSE_TIME] #get response time self.end = msg.getTimestamp() if self.start is not None: frmt = "%Y-%m-%dT%H:%M:%S.%f" self.time_taken = ( datetime.strptime(self.end, frmt) - datetime.strptime(self.start, frmt)).seconds #get counts and averages self.num_response = 1 if self.num_response is None else self.num_response + 1 tutoring_state[NUMBER_OF_RESPONSE] = self.interval.get( int(self.num_response), 5) self.sum_time_taken = self.time_taken if self.sum_time_taken is None else self.sum_time_taken + self.time_taken tutoring_state[RESPONSE_TIME] = self.time_interval.get( ceil(self.time_taken), 5) tutoring_state[AVG_RESPONSE_TIME] = self.time_interval.get( ceil(self.sum_time_taken / self.num_response), 5) #correctness based responses if msg.getResult() == INCORRECT: tutoring_state[QUALITY_ANSWER] = 1 self.num_incorrect_response = 1 if self.num_incorrect_response is None else self.num_incorrect_response + 1 tutoring_state[NUMBER_OF_INCORRECT] = self.interval.get( int(self.num_incorrect_response), 5) self.sum_time_incorrect = self.time_taken if self.sum_time_incorrect is None else self.sum_time_incorrect + self.time_taken tutoring_state[ AVG_RESPONSE_TIME_INCORRECT] = self.time_interval.get( ceil(self.sum_time_incorrect / self.num_incorrect_response), 5) self.questions[-1][1] = 1 elif msg.getResult() == MIXED: tutoring_state[QUALITY_ANSWER] = 2 self.num_mixed_response = 1 if self.num_mixed_response is None else self.num_mixed_response + 1 tutoring_state[NUMBER_OF_MIXED] = self.interval.get( int(self.num_mixed_response), 5) self.sum_time_mixed = self.time_taken if self.sum_time_mixed is None else self.sum_time_mixed + self.time_taken tutoring_state[ AVG_RESPONSE_TIME_MIXED] = self.time_interval.get( ceil(self.sum_time_mixed / self.num_mixed_response), 5) self.questions[-1][1] = 2 elif msg.getResult() == CORRECT: tutoring_state[QUALITY_ANSWER] = 3 self.num_correct_response = 1 if self.num_correct_response is None else self.num_correct_response + 1 tutoring_state[NUMBER_OF_CORRECT] = self.interval.get( int(self.num_correct_response), 5) self.sum_time_correct = self.time_taken if self.sum_time_correct is None else self.sum_time_correct + self.time_taken tutoring_state[ AVG_RESPONSE_TIME_CORRECT] = self.time_interval.get( ceil(self.sum_time_correct / self.num_correct_response), 5) self.questions[-1][1] = 3 else: print("Incorrect Correctness value") #get score scr = tutoring_state[NUMBER_OF_CORRECT] + ( 0.5 * tutoring_state[NUMBER_OF_MIXED]) tutoring_state[SCORE] = self.interval.get(ceil(float(scr)), 5) #update quality_state tutoring_state[RESP_QUALITY_AFTER_RESPONSE] = quality_state[( tutoring_state[QUALITY_ANSWER], tutoring_state[AFTER_USERRESPONSE_STATE])] except: logInfo( '{0} received RL Coach update message exception: {1}'.format( RL_SERVICE_NAME, self.messageToString(msg)), 2) print(tutoring_state)
def receiveMessage(self, msg): reply = None if msg.getSpeechAct() == INFORM_ACT: """ message format for loading calendars: actor = className or student name verb = electronixTutorUploadCalendarVerb object = ownerType result = iCal data context contains access permissions """ if msg.getVerb() == ELECTRONIX_TUTOR_UPLOAD_CALENDAR_VERB: logInfo( '{0} is processing a {1},{2} message'.format( ICAL_READER_SERVICE_NAME, ELECTRONIX_TUTOR_UPLOAD_CALENDAR_VERB, INFORM_ACT), 4) calendarData = SerializableCalendarData() calendarData.ownerId = msg.getActor() calendarData.ownerType = msg.getObject() #default to public access if none are given calendarData.accessPermissions = msg.getContextValue( CALENDAR_ACCESS_PERMISSIONS_KEY, PUBLIC_PERMISSION) calendarInput = msg.getResult() #Calendar library needs to have an encoding #calendarData.calendarData = calendarInput.encode('UTF-8') calendarData.calendarData = calendarInput self.createCalendarData(calendarData.ownerId, calendarData.ownerType, calendarData.accessPermissions, calendarInput) reply = Message(STORAGE_SERVICE_NAME, VALUE_VERB, calendarData.getId(), calendarData, INFORM_ACT, context=msg.getContext()) if msg.getSpeechAct() == REQUEST_ACT: """ message format for adding a task or topic to a calendar: actor = ICAL_READER_SERVICE_NAME verb = addTaskToCalendar object = ownerId result = task or topic data context = startTime (required), endTime(optional), duration(optional) """ if msg.getVerb() == ADD_EVENT_TO_CALENDAR_VERB: logInfo( '{0} is processing a {1},{2} message'.format( ICAL_READER_SERVICE_NAME, ADD_EVENT_TO_CALENDAR_VERB, REQUEST_ACT), 4) startTime = msg.getContextValue(CALENDAR_EVENT_START_TIME_KEY, None) calendarData = self.DB_BRIDGE.getCalendarFromOwnerId( msg.getObject()) endTime = msg.getContextValue(CALENDAR_EVENT_END_TIME_KEY, None) duration = msg.getContextValue(CALENDAR_EVENT_DURATION_KEY, None) if isinstance(msg.getResult(), LearningTask): self.addTaskToCalendar(msg.getResult(), calendarData, startTime, endTime, duration) calendarData.saveToDB() elif isinstance(msg.getResult(), SerializableTopic): self.addTopicToCalendar(msg.getResult(), calendarData, startTime, endTime, duration) calendarData.saveToDB() else: logInfo("no task or topic given, cannot create event", 2) """ message format for lookup up information from a calendar actor = ICAL_READER_SERVICE_NAME verb = calendarLookup object = ownerId result = 'taskId' or 'topicId' defaults to taskID context = startTime (optional), endTime(optional), duration(optional) """ if msg.getVerb() == CALENDAR_LOOKUP_VERB: logInfo( '{0} is processing a {1},{2} message'.format( ICAL_READER_SERVICE_NAME, CALENDAR_LOOKUP_VERB, REQUEST_ACT), 4) startTime = msg.getContextValue(CALENDAR_LOOKUP_START_TIME_KEY, None) endTime = msg.getContextValue(CALENDAR_LOOKUP_END_TIME_KEY, None) duration = msg.getContextValue( CALENDAR_LOOKUP_RELATIVE_TIME_KEY, None) eventType = msg.getContextValue(CALENDAR_LOOKUP_EVENT_TYPE_KEY, TASK_ID) calendarData = self.DB_BRIDGE.getCalendarFromOwnerId( msg.getObject()) taskOrTopicList = self.lookupEventInformation( calendarData, eventType, startTime, endTime, duration) reply = Message(actor=ICAL_READER_SERVICE_NAME, verb=CALENDAR_LOOKUP_VERB, object=eventType, result=taskOrTopicList, context=msg.getContext()) """ message format for requesting information from a calendar actor = ICAL_READER_SERVICE_NAME verb = requestCalendar object = ownerId """ if msg.getVerb() == REQUEST_CALENDAR_VERB: logInfo( '{0} is processing a {1},{2} message'.format( ICAL_READER_SERVICE_NAME, REQUEST_CALENDAR_VERB, REQUEST_ACT), 4) calendarData = self.DB_BRIDGE.getCalendarFromOwnerId( msg.getObject()) iCalData = calendarData.calendarData #iCalDataAsBytes = calendarData.calendarData #iCalDataAsString = iCalDataAsBytes.decode('UTF-8') reply = Message(actor=ICAL_READER_SERVICE_NAME, verb=REQUEST_CALENDAR_VERB, obj=msg.getObject(), result=iCalData, context=msg.getContext()) """ message format for requesting the table of contents actor = ICAL_READER_SERVICE_NAME verb = tableOfContents object = ownerId context = startTime (optional), endTime(optional), duration(optional) """ if msg.getVerb() == TABLE_OF_CONTENTS_VERB: logInfo( '{0} is processing a {1},{2} message'.format( ICAL_READER_SERVICE_NAME, TABLE_OF_CONTENTS_VERB, REQUEST_ACT), 4) calendarData = self.DB_BRIDGE.getCalendarFromOwnerId( msg.getObject()) startTime = msg.getContextValue(CALENDAR_LOOKUP_START_TIME_KEY, None) endTime = msg.getContextValue(CALENDAR_LOOKUP_END_TIME_KEY, None) duration = msg.getContextValue( CALENDAR_LOOKUP_RELATIVE_TIME_KEY, None) topicList = self.lookupEventInformation( calendarData, TOPIC_ID, startTime, endTime, duration) taskList = self.lookupEventInformation(calendarData, TASK_ID, startTime, endTime, duration) topicTaskDictionary = self.buildTableOfContents( topicList, taskList) reply = Message(actor=ICAL_READER_SERVICE_NAME, verb=TABLE_OF_CONTENTS_VERB, object=msg.getObject(), result=topicTaskDictionary, context=msg.getContext()) if reply is not None: logInfo( '{0} is broadcasting a {1}, {2} message'.format( ICAL_READER_SERVICE_NAME, INFORM_ACT, VALUE_VERB), 4) self.sendMessage(reply)
def updateStateRLCoach(self,msg): #state update on relevant messages try: #update scenario if BEGIN_AAR in msg.getVerb(): logInfo('{0} received scenario update message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) #set previous values tutoring_state[SCENARIO_NUMBER] = 2 tutoring_state[SCORE_PREV] = tutoring_state[SCORE] tutoring_state[NUMBER_OF_RESPONSE_PREV] = tutoring_state[NUMBER_OF_RESPONSE] tutoring_state[NUMBER_OF_CORRECT_PREV] = tutoring_state[NUMBER_OF_CORRECT] tutoring_state[NUMBER_OF_MIXED_PREV] = tutoring_state[NUMBER_OF_MIXED] tutoring_state[NUMBER_OF_INCORRECT_PREV] = tutoring_state[NUMBER_OF_INCORRECT] tutoring_state[AVG_RESPONSE_TIME_PREV] = tutoring_state[AVG_RESPONSE_TIME] tutoring_state[AVG_RESPONSE_TIME_CORRECT_PREV] = tutoring_state[AVG_RESPONSE_TIME_CORRECT] tutoring_state[AVG_RESPONSE_TIME_MIXED_PREV] = tutoring_state[AVG_RESPONSE_TIME_MIXED] tutoring_state[AVG_RESPONSE_TIME_INCORRECT_PREV] = tutoring_state[AVG_RESPONSE_TIME_INCORRECT] #reset current values tutoring_state[QUALITY_ANSWER_LAST_LAST] = 0 tutoring_state[QUALITY_ANSWER_LAST] = 0 tutoring_state[QUALITY_ANSWER] = 0 tutoring_state[SCORE] = 0 tutoring_state[SEEN_BEFORE] = 0 tutoring_state[QUALITY_PREV_IF_SEEN] = 0 tutoring_state[NUMBER_OF_RESPONSE] = 0 tutoring_state[NUMBER_OF_CORRECT] = 0 tutoring_state[NUMBER_OF_INCORRECT] = 0 tutoring_state[NUMBER_OF_MIXED] = 0 tutoring_state[RESPONSE_TIME] = 0 tutoring_state[RESPONSE_TIME_LAST] = 0 tutoring_state[RESPONSE_TIME_LAST_LAST] = 0 tutoring_state[AVG_RESPONSE_TIME] = 0 tutoring_state[AVG_RESPONSE_TIME_CORRECT] = 0 tutoring_state[AVG_RESPONSE_TIME_INCORRECT] = 0 tutoring_state[AVG_RESPONSE_TIME_MIXED] = 0 #recent locals for current self.num_response = None self.num_correct_response = None self.num_incorrect_response = None self.num_mixed_response = None self.start = None self.end = None self.time_taken = None self.time_correct = None self.time_mixed = None self.time_incorrect = None #get Gender elif REGISTER_USER_INFO in msg.getVerb(): logInfo('{0} received gender update message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) gend = msg.getObject() if gend == FEMALE: tutoring_state[GENDER] = 2 elif gend == MALE: tutoring_state[GENDER] = 1 #update response time #verb should be GameLog, the object should be PracticeEnvironment and the result should be RandomizedChoices if msg.getVerb() == GAME_LOG and msg.getObject() == PRACTICE_ENVIRONMENT and msg.getResult() == RANDOMIZED_CHOICES: logInfo('{0} received start timestamp update message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) self.start = msg.getTimestamp() print("start = ",self.start) #once the participant answers elif TRANSCRIPT_UPDATE in msg.getVerb(): logInfo('{0} received transcript update message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) #store unique ID of node if tutoring_state[SCENARIO_NUMBER] == 1: logInfo('{0} received question store message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) node_id = msg.getContextValue(NODE_ID_CONTEXT_KEY) node = [node_id, 0] #quality null - will be updated when checked for correctness self.questions.append(node) #check if Chen's Utterances stored before if tutoring_state[SCENARIO_NUMBER] == 2: logInfo('{0} received if seen before message: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) node_id = msg.getContextValue(NODE_ID_CONTEXT_KEY) for question in self.questions: if question[0] == node_id: tutoring_state[SEEN_BEFORE] = 1 tutoring_state[QUALITY_PREV_IF_SEEN] = question[1] break else: tutoring_state[SEEN_BEFORE] = 0 tutoring_state[QUALITY_PREV_IF_SEEN] = 0 print(self.start) #update lasts tutoring_state[QUALITY_ANSWER_LAST_LAST] = tutoring_state[QUALITY_ANSWER_LAST] tutoring_state[QUALITY_ANSWER_LAST] = tutoring_state[QUALITY_ANSWER] tutoring_state[RESPONSE_TIME_LAST_LAST] = tutoring_state[RESPONSE_TIME_LAST] tutoring_state[RESPONSE_TIME_LAST] = tutoring_state[RESPONSE_TIME] #get response time self.end = msg.getTimestamp() if self.start is not None: frmt = "%Y-%m-%dT%H:%M:%S.%f" self.time_taken = (datetime.strptime(self.end, frmt) - datetime.strptime(self.start, frmt)).seconds #get counts and averages self.num_response = 1 if self.num_response is None else self.num_response + 1 tutoring_state[NUMBER_OF_RESPONSE] = self.interval.get(int(self.num_response),5) self.sum_time_taken = self.time_taken if self.sum_time_taken is None else self.sum_time_taken + self.time_taken tutoring_state[RESPONSE_TIME] = self.time_interval.get(ceil(self.time_taken),5) tutoring_state[AVG_RESPONSE_TIME] = self.time_interval.get(ceil(self.sum_time_taken/self.num_response),5) #correctness based responses if msg.getResult() == INCORRECT: tutoring_state[QUALITY_ANSWER] = 1 self.num_incorrect_response = 1 if self.num_incorrect_response is None else self.num_incorrect_response + 1 tutoring_state[NUMBER_OF_INCORRECT] = self.interval.get(int(self.num_incorrect_response),5) self.sum_time_incorrect = self.time_taken if self.sum_time_incorrect is None else self.sum_time_incorrect + self.time_taken tutoring_state[AVG_RESPONSE_TIME_INCORRECT] = self.time_interval.get(ceil(self.sum_time_incorrect/self.num_incorrect_response),5) self.questions[-1][1] = 1 elif msg.getResult() == MIXED: tutoring_state[QUALITY_ANSWER] = 2 self.num_mixed_response = 1 if self.num_mixed_response is None else self.num_mixed_response + 1 tutoring_state[NUMBER_OF_MIXED] = self.interval.get(int(self.num_mixed_response),5) self.sum_time_mixed = self.time_taken if self.sum_time_mixed is None else self.sum_time_mixed + self.time_taken tutoring_state[AVG_RESPONSE_TIME_MIXED] = self.time_interval.get(ceil(self.sum_time_mixed/self.num_mixed_response),5) self.questions[-1][1] = 2 elif msg.getResult() == CORRECT: tutoring_state[QUALITY_ANSWER] = 3 self.num_correct_response = 1 if self.num_correct_response is None else self.num_correct_response + 1 tutoring_state[NUMBER_OF_CORRECT] = self.interval.get(int(self.num_correct_response),5) self.sum_time_correct = self.time_taken if self.sum_time_correct is None else self.sum_time_correct + self.time_taken tutoring_state[AVG_RESPONSE_TIME_CORRECT] = self.time_interval.get(ceil(self.sum_time_correct/self.num_correct_response),5) self.questions[-1][1] = 3 else: print("Incorrect Correctness value") #get score scr = tutoring_state[NUMBER_OF_CORRECT] + (0.5 * tutoring_state[NUMBER_OF_MIXED]) tutoring_state[SCORE] = self.interval.get(ceil(float(scr)),5) #update quality_state tutoring_state[RESP_QUALITY_AFTER_RESPONSE] = quality_state[(tutoring_state[QUALITY_ANSWER], tutoring_state[AFTER_USERRESPONSE_STATE])] except: logInfo('{0} received RL Coach update message exception: {1}'.format(RL_SERVICE_NAME, self.messageToString(msg)), 2) print(tutoring_state)
def saveToDB(self): existingTasksWithSameName = DBTask.find_by_index('nameIndex', self.name) existingTask = None logInfo("assistmentsItemcacheValue2 = {0}".format(self.assistmentsItemCache), 6) for possibleExistingTask in existingTasksWithSameName: if self.ids == possibleExistingTask.ids: existingTask = possibleExistingTask if existingTask is None: logInfo("task with name {0} does not yet exist".format(self.name), 3) if self.assistmentsItemCache: self.assistmentsItemCache.saveToDB() self.assistmentsItemId = self.assistmentsItemCache.id logInfo("assistmentsItemId = {0}".format(self.assistmentsItemId), 6) logInfo("assistmentsItemcacheValue4 = {0}".format(self.assistmentsItemCache), 6) self.save() for kc in self.kcs:#TODO: figure out what tod do with these alias = DBKCTaskAssociations() alias.kc = kc alias.taskId = self.id alias.save() else: logInfo("task with name {0} already exists, overwriting".format(self.name), 3) existingTask.name = self.name existingTask.displayName = self.displayName existingTask.ids = self.ids existingTask.kcs = self.kcs existingTask.baseURL = self.baseURL existingTask.description = self.description existingTask.canBeRecommendedIndividually = self.canBeRecommendedIndividually self.assistmentsItemCache.id = existingTask.assistmentsItemId existingTask.assistmentsItemCache = self.assistmentsItemCache if existingTask.assistmentsItemCache: existingTask.assistmentsItemCache.saveToDB() existingTask.assistmentsItemId = existingTask.assistmentsItemCache.id logInfo("assistmentsItemcacheValue3 = {0}".format(existingTask.assistmentsItemCache), 6) logInfo("assistmentsItemId = {0}".format(existingTask.assistmentsItemId), 6) existingTask.save() return self.id