def test_detail_view(request, test_id): """View details of student performance on specific exams""" facility, group_id, context = coach_nav_context(request, "test") # get users in this facility and group users = get_user_queryset(request, facility, group_id) # Get test object test_resource = TestResource() test_obj = test_resource._read_test(test_id=test_id) # get all of the test logs for this specific test object and generated by these specific users if group_id: test_logs = TestLog.objects.filter(user__group=group_id, test=test_id) # Narrow all by ungroup facility user if group_id == control_panel_api_resources.UNGROUPED_KEY: if facility: test_logs = TestLog.objects.filter(user__group__isnull=True) else: test_logs = TestLog.objects.filter(facility=facility, user__group__isnull=True) else: # covers the all groups case test_logs = TestLog.objects.filter(user__facility=facility, test=test_id) results_table, scores_dict = OrderedDict(), OrderedDict() # build this up now to use in summary stats section ex_ids = set(literal_eval(test_obj.ids)) for ex in ex_ids: scores_dict[ex] = [] for s in users: s.name = s.get_name() user_attempts = AttemptLog.objects.filter(user=s, context_type='test', context_id=test_id) results_table[s] = [] attempts_count_total, attempts_count_correct_total = 0, 0 for ex in ex_ids: attempts = [attempt for attempt in user_attempts if attempt.exercise_id == ex] attempts_count = len(attempts) attempts_count_correct = len([attempt for attempt in attempts if attempt.correct]) attempts_count_total += attempts_count attempts_count_correct_total += attempts_count_correct if attempts_count: score = round(100 * float(attempts_count_correct)/float(attempts_count), 1) scores_dict[ex].append(score) display_score = "%d%%" % score else: score = '' display_score = '' results_table[s].append({ 'display_score': display_score, 'raw_score': score, }) # Calc overall score if attempts_count_total: score = round(100 * float(attempts_count_correct_total)/float(attempts_count_total), 1) display_score = "%d%%" % score fraction_correct = "(%(correct)d/%(attempts)d)" % ({'correct': attempts_count_correct_total, 'attempts': attempts_count_total}) else: score = '' display_score = '' fraction_correct = '' results_table[s].append({ 'display_score': display_score, 'raw_score': score, 'title': fraction_correct, }) # This retrieves stats for individual exercises stats_dict = OrderedDict() for stat in SUMMARY_STATS: stats_dict[stat] = [] for ex in ex_ids: scores_list = scores_dict[ex] if scores_list: stats_dict[stat].append("%d%%" % return_list_stat(scores_list, stat)) else: stats_dict[stat].append('') # replace the exercise ids with their full names exercises = get_exercise_cache() ex_titles = [] for ex in ex_ids: ex_titles.append(exercises[ex]['title']) # provide a list of test options to view for this group/facility combo if group_id: test_logs = TestLog.objects.filter(user__group=group_id) else: # covers the all/no groups case test_logs = TestLog.objects.filter(user__facility=facility) test_objects = test_resource._read_tests() unique_test_ids = set([test_log.test for test_log in test_logs]) test_options = [{'id': obj.test_id, 'url': reverse('test_detail_view', kwargs={'test_id':obj.test_id}), 'title': obj.title} for obj in test_objects if obj.test_id in unique_test_ids] context = plotting_metadata_context(request, facility=facility) context.update({ "test_obj": test_obj, "ex_cols": ex_titles, "results_table": results_table, "stats_dict": stats_dict, "test_options": test_options, }) return context
def test_detail_view(request, test_id): """View details of student performance on specific exams""" facility, group_id, context = coach_nav_context(request, "test") # get users in this facility and group users = get_user_queryset(request, facility, group_id) # Get test object test_resource = TestResource() test_obj = test_resource._read_test(test_id=test_id) # get all of the test logs for this specific test object and generated by these specific users if group_id: test_logs = TestLog.objects.filter(user__group=group_id, test=test_id) # Narrow all by ungroup facility user if group_id == control_panel_api_resources.UNGROUPED_KEY: if facility: test_logs = TestLog.objects.filter(user__group__isnull=True) else: test_logs = TestLog.objects.filter(facility=facility, user__group__isnull=True) else: # covers the all groups case test_logs = TestLog.objects.filter(user__facility=facility, test=test_id) results_table, scores_dict = OrderedDict(), OrderedDict() # build this up now to use in summary stats section ex_ids = set(literal_eval(test_obj.ids)) for ex in ex_ids: scores_dict[ex] = [] for s in users: s.name = s.get_name() user_attempts = AttemptLog.objects.filter(user=s, context_type='test', context_id=test_id) results_table[s] = [] attempts_count_total, attempts_count_correct_total = 0, 0 for ex in ex_ids: attempts = [ attempt for attempt in user_attempts if attempt.exercise_id == ex ] attempts_count = len(attempts) attempts_count_correct = len( [attempt for attempt in attempts if attempt.correct]) attempts_count_total += attempts_count attempts_count_correct_total += attempts_count_correct if attempts_count: score = round( 100 * float(attempts_count_correct) / float(attempts_count), 1) scores_dict[ex].append(score) display_score = "%d%%" % score else: score = '' display_score = '' results_table[s].append({ 'display_score': display_score, 'raw_score': score, }) # Calc overall score if attempts_count_total: score = round( 100 * float(attempts_count_correct_total) / float(attempts_count_total), 1) display_score = "%d%%" % score fraction_correct = "(%(correct)d/%(attempts)d)" % ( { 'correct': attempts_count_correct_total, 'attempts': attempts_count_total }) else: score = '' display_score = '' fraction_correct = '' results_table[s].append({ 'display_score': display_score, 'raw_score': score, 'title': fraction_correct, }) # This retrieves stats for individual exercises stats_dict = OrderedDict() for stat in SUMMARY_STATS: stats_dict[stat] = [] for ex in ex_ids: scores_list = scores_dict[ex] if scores_list: stats_dict[stat].append("%d%%" % return_list_stat(scores_list, stat)) else: stats_dict[stat].append('') # replace the exercise ids with their full names exercises = get_exercise_cache() ex_titles = [] for ex in ex_ids: ex_titles.append(exercises[ex]['title']) # provide a list of test options to view for this group/facility combo if group_id: test_logs = TestLog.objects.filter(user__group=group_id) else: # covers the all/no groups case test_logs = TestLog.objects.filter(user__facility=facility) test_objects = test_resource._read_tests() unique_test_ids = set([test_log.test for test_log in test_logs]) test_options = [{ 'id': obj.test_id, 'url': reverse('test_detail_view', kwargs={'test_id': obj.test_id}), 'title': obj.title } for obj in test_objects if obj.test_id in unique_test_ids] context = plotting_metadata_context(request, facility=facility) context.update({ "test_obj": test_obj, "ex_cols": ex_titles, "results_table": results_table, "stats_dict": stats_dict, "test_options": test_options, }) return context
def test_view(request): """Test view gets data server-side and displays exam results""" facility, group_id, context = coach_nav_context(request, "test") # Get students users = get_user_queryset(request, facility, group_id) # Get the TestLog objects generated by this group of students # TODO(cpauya): what about queryset for ungrouped students? test_logs = None if group_id: test_logs = TestLog.objects.filter(user__group=group_id) # Narrow all by ungroup facility user if group_id == control_panel_api_resources.UNGROUPED_KEY: test_logs = TestLog.objects.filter(user__group__isnull=True) if facility: TestLog.objects.filter(user__facility=facility, user__group__isnull=True) else: TestLog.objects.filter(user__group__isnull=True) elif facility: test_logs = TestLog.objects.filter(user__facility=facility) else: # filter by all facilities and groups for the user (groups, facilities, ungrouped_available) = get_accessible_objects_from_logged_in_user(request, facility=facility) if facilities: facility_ids = facilities.values_list("id", flat=True) test_logs = TestLog.objects.filter(user__facility__id__in=facility_ids) # Get list of all test objects test_resource = TestResource() tests_list = test_resource._read_tests() # Get completed test objects (used as columns) completed_test_ids = set([item.test for item in test_logs]) test_objects = [test for test in tests_list if test.test_id in completed_test_ids] # Create the table results_table = OrderedDict() for s in users: s.name = s.get_name() user_test_logs = [log for log in test_logs if log.user == s] results_table[s] = [] for t in test_objects: log_object = next((log for log in user_test_logs if log.test == t.test_id), '') # The template expects a status and a score to display if log_object: test_object = log_object.get_test_object() score = round(100 * float(log_object.total_correct) / float(test_object.total_questions), 1) display_score = "%(score)d%% (%(correct)d/%(total_questions)d)" % {'score': score, 'correct': log_object.total_correct, 'total_questions': test_object.total_questions} if log_object.complete: # Case: completed => we show % score if score >= 80: status = _("pass") elif score >= 60: status = _("borderline") else: status = _("fail" ) results_table[s].append({ "status": status, "cell_display": display_score, "title": status.title(), }) else: # Case: has started, but has not finished => we display % score & # remaining in title n_remaining = test_object.total_questions - log_object.index status = _("incomplete") results_table[s].append({ "status": status, "cell_display": display_score, "title": status.title() + ": " + ungettext("%(n_remaining)d problem remaining", n_remaining) % {'n_remaining': n_remaining}, }) else: # Case: has not started status = _("not started") results_table[s].append({ "status": status, "cell_display": "", "title": status.title(), }) # This retrieves stats for students score_list = [round(100 * float(result.total_correct) / float(result.get_test_object().total_questions), 1) for result in user_test_logs] for stat in SUMMARY_STATS: if score_list: results_table[s].append({ "status": "statistic", "cell_display": "%d%%" % return_list_stat(score_list, stat), }) else: results_table[s].append({ "status": "statistic", "cell_display": "", }) # This retrieves stats for tests stats_dict = OrderedDict() for stat in SUMMARY_STATS: stats_dict[stat] = [] for test_obj in test_objects: # get the logs for this test across all users and then add summary stats log_scores = [round(100 * float(test_log.total_correct) / float(test_log.get_test_object().total_questions), 1) for test_log in test_logs if test_log.test == test_obj.test_id] stats_dict[stat].append("%d%%" % return_list_stat(log_scores, stat)) context.update(plotting_metadata_context(request, facility=facility)) context.update({ "results_table": results_table, "test_columns": test_objects, "summary_stats": SUMMARY_STATS, "stats_dict": stats_dict, }) return context
def test_view(request): """Test view gets data server-side and displays exam results""" facility, group_id, context = coach_nav_context(request, "test") # Get students users = get_user_queryset(request, facility, group_id) # Get the TestLog objects generated by this group of students # TODO(cpauya): what about queryset for ungrouped students? test_logs = None if group_id: test_logs = TestLog.objects.filter(user__group=group_id) # Narrow all by ungroup facility user if group_id == control_panel_api_resources.UNGROUPED_KEY: test_logs = TestLog.objects.filter(user__group__isnull=True) if facility: TestLog.objects.filter(user__facility=facility, user__group__isnull=True) else: TestLog.objects.filter(user__group__isnull=True) elif facility: test_logs = TestLog.objects.filter(user__facility=facility) else: # filter by all facilities and groups for the user (groups, facilities, ungrouped_available) = get_accessible_objects_from_logged_in_user( request, facility=facility) if facilities: facility_ids = facilities.values_list("id", flat=True) test_logs = TestLog.objects.filter( user__facility__id__in=facility_ids) # Get list of all test objects test_resource = TestResource() tests_list = test_resource._read_tests() # Get completed test objects (used as columns) completed_test_ids = set([item.test for item in test_logs]) test_objects = [ test for test in tests_list if test.test_id in completed_test_ids ] # Create the table results_table = OrderedDict() for s in users: s.name = s.get_name() user_test_logs = [log for log in test_logs if log.user == s] results_table[s] = [] for t in test_objects: log_object = next( (log for log in user_test_logs if log.test == t.test_id), '') # The template expects a status and a score to display if log_object: test_object = log_object.get_test_object() score = round( 100 * float(log_object.total_correct) / float(test_object.total_questions), 1) display_score = "%(score)d%% (%(correct)d/%(total_questions)d)" % { 'score': score, 'correct': log_object.total_correct, 'total_questions': test_object.total_questions } if log_object.complete: # Case: completed => we show % score if score >= 80: status = _("pass") elif score >= 60: status = _("borderline") else: status = _("fail") results_table[s].append({ "status": status, "cell_display": display_score, "title": status.title(), }) else: # Case: has started, but has not finished => we display % score & # remaining in title n_remaining = test_object.total_questions - log_object.index status = _("incomplete") results_table[s].append({ "status": status, "cell_display": display_score, "title": status.title() + ": " + ungettext("%(n_remaining)d problem remaining", n_remaining) % { 'n_remaining': n_remaining }, }) else: # Case: has not started status = _("not started") results_table[s].append({ "status": status, "cell_display": "", "title": status.title(), }) # This retrieves stats for students score_list = [ round( 100 * float(result.total_correct) / float(result.get_test_object().total_questions), 1) for result in user_test_logs ] for stat in SUMMARY_STATS: if score_list: results_table[s].append({ "status": "statistic", "cell_display": "%d%%" % return_list_stat(score_list, stat), }) else: results_table[s].append({ "status": "statistic", "cell_display": "", }) # This retrieves stats for tests stats_dict = OrderedDict() for stat in SUMMARY_STATS: stats_dict[stat] = [] for test_obj in test_objects: # get the logs for this test across all users and then add summary stats log_scores = [ round( 100 * float(test_log.total_correct) / float(test_log.get_test_object().total_questions), 1) for test_log in test_logs if test_log.test == test_obj.test_id ] stats_dict[stat].append("%d%%" % return_list_stat(log_scores, stat)) context.update(plotting_metadata_context(request, facility=facility)) context.update({ "results_table": results_table, "test_columns": test_objects, "summary_stats": SUMMARY_STATS, "stats_dict": stats_dict, }) return context