diff --git a/TODO b/TODO index 7a1e5ed73f780a0562b01b83a9677e99c881eaf8..3a9f75e77be9a29cd4fc50573ae007467e04fdc0 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,8 @@ - Custom matcher classes +- Enter single grades + Ideas ===== diff --git a/course/analytics.py b/course/analytics.py index 3c3e6a70fbd9a133796be9179694666f5fdf617d..b873fbec6d90931fab51d8ea110940b0df319ea8 100644 --- a/course/analytics.py +++ b/course/analytics.py @@ -246,7 +246,7 @@ def safe_div(num, denom): return num/denom -def make_page_answer_stats_list(pctx, flow_id): +def make_page_answer_stats_list(pctx, flow_id, restrict_to_first_attempt): flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_id, pctx.course_commit_sha) @@ -273,9 +273,14 @@ def make_page_answer_stats_list(pctx, flow_id): )) if is_multiple_submit and connection.features.can_distinct_on_fields: - visits = (visits - .distinct("page_data") - .order_by("page_data", "-visit_time")) + if not restrict_to_first_attempt: + visits = (visits + .distinct("page_data") + .order_by("page_data", "-visit_time")) + else: + visits = (visits + .distinct("flow_session__participation") + .order_by("flow_session__participation", "-visit_time")) visits = (visits .select_related("flow_session") @@ -381,12 +386,17 @@ def flow_analytics(pctx, flow_id): ]: raise PermissionDenied("must be at least TA to view analytics") + restrict_to_first_attempt = int( + bool(pctx.request.GET.get("restrict_to_first_attempt") == "1")) + return render_course_page(pctx, "course/analytics-flow.html", { "flow_identifier": flow_id, "grade_histogram": make_grade_histogram(pctx, flow_id), - "page_answer_stats_list": make_page_answer_stats_list(pctx, flow_id), + "page_answer_stats_list": make_page_answer_stats_list(pctx, flow_id, + restrict_to_first_attempt), "time_histogram": make_time_histogram(pctx, flow_id), "participant_count": count_participants(pctx, flow_id), + "restrict_to_first_attempt": restrict_to_first_attempt, }) # }}} @@ -416,6 +426,9 @@ def page_analytics(pctx, flow_id, group_id, page_id): flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_id, pctx.course_commit_sha) + restrict_to_first_attempt = int( + bool(pctx.request.GET.get("restrict_to_first_attempt") == "1")) + is_multiple_submit = is_flow_multiple_submit(flow_desc) page_cache = PageInstanceCache(pctx.repo, pctx.course, flow_id) @@ -430,9 +443,14 @@ def page_analytics(pctx, flow_id, group_id, page_id): )) if is_multiple_submit and connection.features.can_distinct_on_fields: - visits = (visits - .distinct("page_data", "visit_time") - .order_by("page_data", "-visit_time")) + if restrict_to_first_attempt: + visits = (visits + .distinct("page_data", "visit_time") + .order_by("page_data", "-visit_time")) + else: + visits = (visits + .distinct("flow_session__participation", "visit_time") + .order_by("flow_session__participation", "-visit_time")) visits = (visits .select_related("flow_session") @@ -496,6 +514,7 @@ def page_analytics(pctx, flow_id, group_id, page_id): "title": title, "body": body, "answer_stats_list": answer_stats, + "restrict_to_first_attempt": restrict_to_first_attempt, }) # }}} diff --git a/course/templates/course/analytics-flow.html b/course/templates/course/analytics-flow.html index 86c86b4caee100a997c25248156cd355436b4775..dade6e0d9ec25d03cabc4b9c5c6bbc008dbb8275 100644 --- a/course/templates/course/analytics-flow.html +++ b/course/templates/course/analytics-flow.html @@ -9,6 +9,20 @@
+ {% if restrict_to_first_attempt %} + Showing results for only the first attempt by each participant. + + Show all attempts + + {% else %} + Showing results for all attempts by each participant. + + Show only the first attempt + + {% endif %} +
+{{ grade_histogram.total_weight }} grade{{ grade_histogram.total_weight|pluralize }} {% if participant_count != None %} @@ -24,7 +38,8 @@ {% for astats in page_answer_stats_list %}
+ {% if restrict_to_first_attempt %} + Showing results for only the first attempt by each participant. + + Show all attempts + + {% else %} + Showing results for all attempts by each participant. + + Show only the first attempt + + {% endif %} +
+ +