def get_session_overview(user): """ Returns information about the last session student has been practicing. Returns: namedtuple 'session_overview' """ student = StudentModel.objects.get_or_create(user=user)[0] session = sess_service.get_session(student) if session is None: instances = [] else: instances = session.get_task_instances() if instances == [] or instances[-1].time_end is None: overall_time = 0 else: overall_delta = instances[-1].time_end - instances[0].time_start overall_time = overall_delta.seconds percentils = [] for instance in instances: percentils.append(statistics_service.percentil(instance) if instance.solved else None) return SessionOverview( task_instances = instances, overall_time = overall_time, percentils = percentils )
def process_attempt_report(user, report): """Process reported result of a solution attempt of a task Args: user: current user (user who took the attempt report: dictionary with the following fields: - task-instance-id - attempt - solved - time - code Returns: - whether the task is solved for the first time - number of earned-credits - speed-bonus: bool Raises: ValueError: - If the user argument is None. - If the report doesn't belong to the student. - If it's reporting an obsolete attempt (i.e. new attempt was already processed). """ student = StudentModel.objects.get(user=user) # TODO: move the parsing of parameters to the view task_instance_id = report['task-instance-id'] attempt_count = report['attempt'] solved = report['solved'] time = report['time'] code = report['code'] logger.info("Reporting attempt for student %s with result %s", student.pk, solved) task_instance = TaskInstanceModel.objects.get(id=task_instance_id) if attempt_count < task_instance.attempt_count: # It means that this report is obsolete. Note that we allow for # equality of attempts count, which means that we want to update the # last report with more information (e.g. added flow report). raise ValueError("Obsolete attempt report can't be processed.") if student.pk != task_instance.student.pk: raise ValueError("Report doesn't belong to the student.") task_instance.update_after_attempt( attempt_count=attempt_count, time=time, solved=solved, ) task_instance.save() task = task_instance.task student_task_info = StudentTaskInfoModel.objects.get_or_create(student=student, task=task)[0] solved_before = student_task_info.last_solved_instance is not None student_task_info.update(task_instance) student_task_info.save() if solved: see_task_concepts(student, task) credits = 0 speed_bonus = False progress = [] time, percentil = None, None if solved: task = task_instance.task time = task_instance.time_spent percentil = statistics_service.percentil(task_instance) if not solved_before: level = task.get_level() credits, speed_bonus = compute_credits(level, percentil) task_instance.earned_credits = credits task_instance.speed_bonus = speed_bonus progress = level_progress(student, credits) student.save() task_instance.save() Attempt.objects.create( task_instance=task_instance, order=task_instance.attempt_count, success=task_instance.solved, code=code ) task_solved_first_time = solved and not solved_before logger.info("Reporting attempt was successful for student %s with result %s", student.pk, solved) result = namedtuple('processAttemptReportResult', ['task_solved_first_time', 'time', 'percentil', 'credits', 'speed_bonus', 'progress'])\ (task_solved_first_time, time, percentil, credits, speed_bonus, progress) return result