diff --git a/analyze_grades.py b/analyze_grades.py index cd8d02ba9ad97c7e87a14e345b3f0aae9928df0f..66e48be468df6b865f706dbc461d014c162a38ef 100644 --- a/analyze_grades.py +++ b/analyze_grades.py @@ -3,6 +3,7 @@ import statistics import sys from typing import List, Optional, Dict, Set +import common_functions from api.canvas_classes import CanvasAssignment, CanvasAssignmentGroup, CanvasCourse, CanvasUser from common_functions import select_from_list from majors import Major @@ -48,10 +49,13 @@ def create_semester_filter() -> str: def print_statistics_for_some_majors(assignment: CanvasAssignment, majors: Set[Major], - major_partitions: Dict[Major, Set[CanvasUser]]) -> None: + major_partitions: Dict[Major, Set[CanvasUser]], + students: Optional[List[CanvasUser]] = None) -> None: points_possible: float = assignment.get_points_possible() for major in majors: - scores: List[float] = [assignment.get_score(student) for student in major_partitions[major] + student_subset: Set[CanvasUser] = major_partitions[major] if students is None \ + else major_partitions[major].intersection(students) + scores: List[float] = [assignment.get_score(student) for student in student_subset if assignment.get_score(student) is not None] try: average_score: float = statistics.mean(scores) @@ -70,14 +74,37 @@ def print_statistics(assignment: CanvasAssignment, major_partitions: Dict[Major, print_statistics_for_some_majors(assignment, non_computing_majors, major_partitions) -def assess_assignments(course: CanvasCourse, major_partitions: Dict[Major, Set[CanvasUser]]) -> None: +def print_statistics_by_section(course: CanvasCourse, assignment: CanvasAssignment, + major_partitions: Dict[Major, Set[CanvasUser]]) -> None: + print(f'Statistics for {assignment}:') + computing_majors: Set[Major] = {major for major in Major.majors if major.is_computing_major} + non_computing_majors: Set[Major] + all_non_computing_majors: Set[Major] = {major for major in major_partitions.keys() if not major.is_computing_major} + for section in course.get_sections(): + print(section) + students: List[CanvasUser] = section.get_students() + # noinspection PyTypeChecker + non_computing_majors = set() # why does PyCharm think set() returns Set[set]? + for student in students: + non_computing_majors.update({major for major in all_non_computing_majors + if student in major_partitions[major]}) + print_statistics_for_some_majors(assignment, computing_majors, major_partitions, students) + print_statistics_for_some_majors(assignment, non_computing_majors, major_partitions, students) + print() + + +def assess_assignments(course: CanvasCourse, major_partitions: Dict[Major, Set[CanvasUser]], + print_section_statistics: bool = False) -> None: print('You may now select the assignments to assess.') answer: str = 'Yes' while answer == '' or answer[0].upper() != 'N': assignment_group: CanvasAssignmentGroup = \ select_from_list(course.get_assignment_groups(), 'assignment group') oat_assignment: CanvasAssignment = select_from_list(assignment_group.get_assignments(), 'assignment') - print_statistics(oat_assignment, major_partitions) + if not print_section_statistics: + print_statistics(oat_assignment, major_partitions) + else: + print_statistics_by_section(course, oat_assignment, major_partitions) print() answer = input('Assess additional assignments? [Y/n] ') @@ -104,7 +131,10 @@ def assess_course(course: CanvasCourse) -> None: print() print(f'There are {len(major_partitions)} majors among the students ' f'(some students may have more than one major).') - assess_assignments(course, major_partitions) + print(f'There are {len(course.get_sections())} sections in the course. In most cases, you only need to print ' + f'aggregate statistics for the full course. ', end='') + answer = input('Do you want to print statistics for each section instead? [y/N] ') + assess_assignments(course, major_partitions, answer != '' and answer[0].upper() == 'Y') print() diff --git a/api/canvas_classes.py b/api/canvas_classes.py index 5582bd049b9cab21ddfa0809f7e0cf99d253623c..04f698eca91f42d5eb85fdc71f754b765cedb402 100644 --- a/api/canvas_classes.py +++ b/api/canvas_classes.py @@ -889,7 +889,7 @@ class CanvasCourseSection: elif len(candidates) > 1: print(f'ERROR: Indirectly found {len(candidates)} canvas users for {user_json["name"]} ' f'using the "unique" login {user_json["login_id"]}. Adding none of them.') - else: + elif user_json["name"] != "Test Student": print(f'ERROR: Could not locate canvas user: {user_json["name"]}') return students @@ -947,7 +947,6 @@ class CanvasCourse: courses = [CanvasCourse(course.id) for course in canvas_courses if semester_filter in course.course_code] return courses - def __init__(self, course_id: int): self.canvas_course = CanvasSession.get_session().get_course(course_id) diff --git a/majors.py b/majors.py index 61ff534dfc10d75ef3c2a04d517202fd3fac7d3f..e26ef7a6067be0159800b5f6e700978a388e8c62 100644 --- a/majors.py +++ b/majors.py @@ -16,7 +16,8 @@ class Major: @classmethod def get_major(cls, name: str) -> "Major": - candidate = [major for major in cls.majors if name == major.name or name in major.alternate_names] + candidate = [major for major in cls.majors if name.lower() == major.name.lower() + or name.lower() in [alternate_name.lower() for alternate_name in major.alternate_names]] if candidate: return candidate[0] else: @@ -29,7 +30,7 @@ class Major: return {Major.get_major('Graduate Student')} else: majors: Optional[Set[str]] = student_data['unlSISMajor'] - return {Major.get_major(major) for major in majors} if majors is not None else Major.get_major('None') + return {Major.get_major(major) for major in majors} if majors is not None else {Major.get_major('None')} @property def name(self) -> str: