def test_post_submission_for_student_on_accessing(self): course = get_course_with_access(self.student_on_accessing, 'load', self.course_id) dry_run_result = post_submission_for_student(self.student_on_accessing, course, self.problem_location, self.open_ended_task_number, dry_run=True) self.assertFalse(dry_run_result) with patch('capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_send_to_queue: mock_send_to_queue.return_value = (0, "Successfully queued") module = get_module_for_student(self.student_on_accessing, self.problem_location) task = module.child_module.get_task_number(self.open_ended_task_number) student_response = "Here is an answer." student_anonymous_id = anonymous_id_for_user(self.student_on_accessing, None) submission_time = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) result = post_submission_for_student(self.student_on_accessing, course, self.problem_location, self.open_ended_task_number, dry_run=False) self.assertTrue(result) mock_send_to_queue_body_arg = json.loads(mock_send_to_queue.call_args[1]['body']) self.assertEqual(mock_send_to_queue_body_arg['max_score'], 2) self.assertEqual(mock_send_to_queue_body_arg['student_response'], student_response) body_arg_student_info = json.loads(mock_send_to_queue_body_arg['student_info']) self.assertEqual(body_arg_student_info['anonymous_student_id'], student_anonymous_id) self.assertGreaterEqual(body_arg_student_info['submission_time'], submission_time)
def test_post_submission_for_student_on_accessing(self): course = get_course_with_access(self.student_on_accessing, self.course_id, "load") dry_run_result = post_submission_for_student( self.student_on_accessing, course, self.problem_location, self.open_ended_task_number, dry_run=True ) self.assertFalse(dry_run_result) with patch("capa.xqueue_interface.XQueueInterface.send_to_queue") as mock_send_to_queue: mock_send_to_queue.return_value = (0, "Successfully queued") module = get_module_for_student(self.student_on_accessing, course, self.problem_location) task = module.child_module.get_task_number(self.open_ended_task_number) qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) student_info = { "anonymous_student_id": anonymous_id_for_user(self.student_on_accessing, ""), "submission_time": qtime, } contents = task.payload.copy() contents.update( {"max_score": 2, "student_info": json.dumps(student_info), "student_response": "Here is an answer."} ) result = post_submission_for_student( self.student_on_accessing, course, self.problem_location, self.open_ended_task_number, dry_run=False ) self.assertTrue(result) mock_send_to_queue.assert_called_with(body=json.dumps(contents), header=ANY)
def test_post_submission_for_student_on_accessing(self): course = get_course_with_access(self.student_on_accessing, self.course_id, 'load') dry_run_result = post_submission_for_student(self.student_on_accessing, course, self.problem_location, self.open_ended_task_number, dry_run=True) self.assertFalse(dry_run_result) with patch('capa.xqueue_interface.XQueueInterface.send_to_queue') as mock_send_to_queue: mock_send_to_queue.return_value = (0, "Successfully queued") module = get_module_for_student(self.student_on_accessing, course, self.problem_location) task = module.child_module.get_task_number(self.open_ended_task_number) qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat) student_info = {'anonymous_student_id': anonymous_id_for_user(self.student_on_accessing, ''), 'submission_time': qtime} contents = task.payload.copy() contents.update({ 'max_score': 2, 'student_info': json.dumps(student_info), 'student_response': "Here is an answer.", }) result = post_submission_for_student(self.student_on_accessing, course, self.problem_location, self.open_ended_task_number, dry_run=False) self.assertTrue(result) mock_send_to_queue.assert_called_with(body=json.dumps(contents), header=ANY)
def get_raw(self, command="all"): """Get raw data of progress.""" if not OPERATION.has_key(command): log.error('Invalid command: {}'.format(command)) raise InvalidCommand("Invalid command: {}".format(command)) if command == "summary": return self.courseware_summary self.courseware_summary["graded_students"] = 0 student_count = 0 for student in self.students.iterator(): student_count += 1 if (student_count % 100 == 0) or (student_count == self.courseware_summary['active_students']): msg = "Progress %d/%d" % ( student_count, self.courseware_summary['active_students']) if self.update_state is not None: self.update_state(state=msg) log.info(msg) self.request.user = student log.debug(" * Active user: {}".format(student)) grade = grades.grade(student, self.request, self.course) if grade["grade"] is not None: self.courseware_summary["graded_students"] += 1 for category in self.location_list.keys(): if category not in ["problem"]: continue for loc in self.location_list[category]: log.debug(" * Active location: {}".format(loc)) module = get_module_for_student(student, loc) if module is None: log.debug(" * No state found: %s" % (student)) continue self.collect_module_summary(module) cache.set('progress_summary', self.courseware_summary["graded_students"], timeout=24 * 60 * 60) #statistics = self._calc_statistics() #for key in statistics.keys(): # self.module_summary[key].update(statistics[key]) if command == "modules": return self.module_summary return self.courseware_summary, self.module_summary
def post_submission_for_student(student, course, location, task_number, dry_run=True, hostname=None): """If the student's task child_state is ASSESSING post submission to grader.""" print "{0}:{1}".format(student.id, student.username) request = DummyRequest() request.user = student request.host = hostname try: module = get_module_for_student(student, course, location, request=request) if module is None: print " WARNING: No state found." return False latest_task = module.child_module.get_task_number(task_number) if latest_task is None: print " WARNING: No task state found." return False if not isinstance(latest_task, OpenEndedModule): print " ERROR: Not an OpenEndedModule task." return False latest_task_state = latest_task.child_state if latest_task_state == OpenEndedChild.INITIAL: print " WARNING: No submission." elif latest_task_state == OpenEndedChild.POST_ASSESSMENT or latest_task_state == OpenEndedChild.DONE: print " WARNING: Submission already graded." elif latest_task_state == OpenEndedChild.ASSESSING: latest_answer = latest_task.latest_answer() if dry_run: print " Skipped sending submission to grader: {0!r}".format( latest_answer[:100].encode('utf-8')) else: latest_task.send_to_grader(latest_answer, latest_task.system) print " Sent submission to grader: {0!r}".format( latest_answer[:100].encode('utf-8')) return True else: print "WARNING: Invalid task_state: {0}".format(latest_task_state) except Exception as err: # pylint: disable=broad-except print err return False
def yield_students_progress(self): """Yield progress of students as CSV row.""" header_flag = False student_count = 0 for student in self.students.iterator(): student_count += 1 if (student_count % 100 == 0) or (student_count == self.courseware_summary['active_students']): msg = "Progress %d/%d" % ( student_count, self.courseware_summary['active_students']) if self.update_state is not None: self.update_state(state=msg) log.info(msg) self.request.user = student grade = grades.grade(student, self.request, self.course) for category in self.location_list.keys(): if category not in ["problem"]: continue for loc in self.location_list[category]: module = get_module_for_student(student, loc) if module is None: log.debug(" * No state found: %s" % (student)) continue module_data = self._get_module_data(module) csvrow = [ student.username, module.location, student.last_login.strftime("%Y/%m/%d %H:%M:%S %Z"), grade["grade"], grade["percent"] ] if header_flag is False: header = [ "username", "location", "last_login", "grade", "percent" ] for key in module_data.keys(): header.append(key) header_flag = True yield header for key in module_data.keys(): csvrow.append(module_data[key]) yield csvrow
def post_submission_for_student(student, course, location, task_number, dry_run=True, hostname=None): """If the student's task child_state is ASSESSING post submission to grader.""" print "{0}:{1}".format(student.id, student.username) request = DummyRequest() request.user = student request.host = hostname try: module = get_module_for_student(student, location, request=request) if module is None: print " WARNING: No state found." return False latest_task = module.child_module.get_task_number(task_number) if latest_task is None: print " WARNING: No task state found." return False if not isinstance(latest_task, OpenEndedModule): print " ERROR: Not an OpenEndedModule task." return False latest_task_state = latest_task.child_state if latest_task_state == OpenEndedChild.INITIAL: print " WARNING: No submission." elif latest_task_state == OpenEndedChild.POST_ASSESSMENT or latest_task_state == OpenEndedChild.DONE: print " WARNING: Submission already graded." elif latest_task_state == OpenEndedChild.ASSESSING: latest_answer = latest_task.latest_answer() if dry_run: print " Skipped sending submission to grader: {0!r}".format(latest_answer[:100].encode('utf-8')) else: latest_task.send_to_grader(latest_answer, latest_task.system) print " Sent submission to grader: {0!r}".format(latest_answer[:100].encode('utf-8')) return True else: print "WARNING: Invalid task_state: {0}".format(latest_task_state) except Exception as err: # pylint: disable=broad-except print err return False
def calculate_task_statistics(students, course, location, task_number, write_to_file=True): """Print stats of students.""" stats = { OpenEndedChild.INITIAL: 0, OpenEndedChild.ASSESSING: 0, OpenEndedChild.POST_ASSESSMENT: 0, OpenEndedChild.DONE: 0 } students_with_saved_answers = [] students_with_ungraded_submissions = [] # pylint: disable=invalid-name students_with_graded_submissions = [] # pylint: disable=invalid-name students_with_no_state = [] student_modules = StudentModule.objects.filter(module_state_key=location, student__in=students).order_by('student') print "Total student modules: {0}".format(student_modules.count()) for index, student_module in enumerate(student_modules): if index % 100 == 0: print "--- {0} students processed ---".format(index) student = student_module.student print "{0}:{1}".format(student.id, student.username) module = get_module_for_student(student, course, location) if module is None: print " WARNING: No state found" students_with_no_state.append(student) continue latest_task = module.child_module.get_task_number(task_number) if latest_task is None: print " No task state found" students_with_no_state.append(student) continue task_state = latest_task.child_state stats[task_state] += 1 print " State: {0}".format(task_state) if task_state == OpenEndedChild.INITIAL: if latest_task.stored_answer is not None: students_with_saved_answers.append(student) elif task_state == OpenEndedChild.ASSESSING: students_with_ungraded_submissions.append(student) elif task_state == OpenEndedChild.POST_ASSESSMENT or task_state == OpenEndedChild.DONE: students_with_graded_submissions.append(student) location = Location(location) print "----------------------------------" print "Time: {0}".format(time.strftime("%Y %b %d %H:%M:%S +0000", time.gmtime())) print "Course: {0}".format(course.id) print "Location: {0}".format(location) print "No state: {0}".format(len(students_with_no_state)) print "Initial State: {0}".format(stats[OpenEndedChild.INITIAL] - len(students_with_saved_answers)) print "Saved answers: {0}".format(len(students_with_saved_answers)) print "Submitted answers: {0}".format(stats[OpenEndedChild.ASSESSING]) print "Received grades: {0}".format(stats[OpenEndedChild.POST_ASSESSMENT] + stats[OpenEndedChild.DONE]) print "----------------------------------" if write_to_file: filename = "stats.{0}.{1}".format(location.course, location.name) time_stamp = time.strftime("%Y%m%d-%H%M%S") with open('{0}.{1}.csv'.format(filename, time_stamp), 'wb') as csv_file: writer = csv.writer(csv_file, delimiter=' ', quoting=csv.QUOTE_MINIMAL) for student in students_with_ungraded_submissions: writer.writerow(("ungraded", student.id, anonymous_id_for_user(student, ''), student.username)) for student in students_with_graded_submissions: writer.writerow(("graded", student.id, anonymous_id_for_user(student, ''), student.username)) return stats
def calculate_task_statistics(students, course, location, task_number, write_to_file=True): """Print stats of students.""" stats = { OpenEndedChild.INITIAL: 0, OpenEndedChild.ASSESSING: 0, OpenEndedChild.POST_ASSESSMENT: 0, OpenEndedChild.DONE: 0 } students_with_saved_answers = [] students_with_ungraded_submissions = [] # pylint: disable=invalid-name students_with_graded_submissions = [] # pylint: disable=invalid-name students_with_no_state = [] student_modules = StudentModule.objects.filter(module_state_key=location, student__in=students).order_by('student') print "Total student modules: {0}".format(student_modules.count()) for index, student_module in enumerate(student_modules): if index % 100 == 0: print "--- {0} students processed ---".format(index) student = student_module.student print "{0}:{1}".format(student.id, student.username) module = get_module_for_student(student, location) if module is None: print " WARNING: No state found" students_with_no_state.append(student) continue latest_task = module.child_module.get_task_number(task_number) if latest_task is None: print " No task state found" students_with_no_state.append(student) continue task_state = latest_task.child_state stats[task_state] += 1 print " State: {0}".format(task_state) if task_state == OpenEndedChild.INITIAL: if latest_task.stored_answer is not None: students_with_saved_answers.append(student) elif task_state == OpenEndedChild.ASSESSING: students_with_ungraded_submissions.append(student) elif task_state == OpenEndedChild.POST_ASSESSMENT or task_state == OpenEndedChild.DONE: students_with_graded_submissions.append(student) print "----------------------------------" print "Time: {0}".format(time.strftime("%Y %b %d %H:%M:%S +0000", time.gmtime())) print "Course: {0}".format(course.id) print "Location: {0}".format(location) print "No state: {0}".format(len(students_with_no_state)) print "Initial State: {0}".format(stats[OpenEndedChild.INITIAL] - len(students_with_saved_answers)) print "Saved answers: {0}".format(len(students_with_saved_answers)) print "Submitted answers: {0}".format(stats[OpenEndedChild.ASSESSING]) print "Received grades: {0}".format(stats[OpenEndedChild.POST_ASSESSMENT] + stats[OpenEndedChild.DONE]) print "----------------------------------" if write_to_file: filename = "stats.{0}.{1}".format(location.course, location.name) time_stamp = time.strftime("%Y%m%d-%H%M%S") with open('{0}.{1}.csv'.format(filename, time_stamp), 'wb') as csv_file: writer = csv.writer(csv_file, delimiter=' ', quoting=csv.QUOTE_MINIMAL) for student in students_with_ungraded_submissions: writer.writerow(("ungraded", student.id, anonymous_id_for_user(student, None), student.username)) for student in students_with_graded_submissions: writer.writerow(("graded", student.id, anonymous_id_for_user(student, None), student.username)) return stats