Source code for pykubegrader.grade_reports.class_grade_report
# # import the password and user from the build folder
# try:
# from pykubegrader.build.passwords import password, user
# except: # noqa: E722
# print("Passwords not found, cannot access database")
import os
import pandas as pd
import tqdm
from pykubegrader.grade_reports.grade_report import GradeReport
from pykubegrader.grade_reports.grading_config import (
assignment_type_list,
skipped_users,
students_to_include,
)
from pykubegrader.telemetry import get_all_students
api_base_url = os.getenv("DB_URL")
student_user = os.getenv("user_name_student")
student_pw = os.getenv("keys_student")
[docs]
class ClassGradeReport:
"""Generates and manages a class-wide grade report.
This class retrieves a list of students, initializes a structured grade report,
and populates it with individual student grade data. The final report includes
both assignment-specific grades and a weighted average grade.
Attributes:
student_list (list): A sorted list of all students in the class.
all_student_grades_df (pd.DataFrame): A DataFrame storing grades for each student,
including assignment scores and a weighted average.
Methods:
setup_class_grades():
Initializes an empty DataFrame with assignment names and weighted average columns.
update_student_grade(student):
Fetches and updates an individual student’s weighted average grades in the DataFrame.
fill_class_grades():
Iterates through all students to populate the class-wide grade report.
"""
def __init__(self, user, password, **kwargs):
"""Initializes the class grade report.
Retrieves the student list using authentication, sorts it, and sets up
the class-wide grade report by initializing and populating a DataFrame.
"""
self.user = user
self.password = password
self.student_list = get_all_students(self.user, self.password)
# Remove skipped users
self.student_list = list(set(self.student_list) - set(skipped_users))
# Only include students in the students_to_include list
self.student_list = [s for s in students_to_include if s in self.student_list]
# Sort the student list
self.student_list.sort()
self.setup_class_grades()
self.fill_class_grades()
self.get_class_stats()
self.make_report(**kwargs)
[docs]
def make_report(self, **kwargs):
"""Makes the class grade report.
Args:
**kwargs: Additional keyword arguments.
"""
try:
title = kwargs.get("title", "Grade Report")
filename = kwargs.get("filename", "Grade_report.html")
from ydata_profiling import ProfileReport
profile = ProfileReport(self.all_student_grades_df, title=title)
profile.to_file(filename)
except Exception:
Warning("ydata_profiling not installed, cannot make report")
[docs]
def setup_class_grades(self):
"""Creates an empty DataFrame to store grades for all students.
The DataFrame contains assignment columns and a "Weighted Average Grade" column,
with students as index labels.
"""
self.all_student_grades_df = pd.DataFrame(
0.0,
dtype=float,
index=self.student_list,
columns=[a.name for a in assignment_type_list]
+ ["Weighted Average Grade w Final", "Weighted Average Grade"],
)
[docs]
def update_student_grade(self, student):
"""Fetches and updates the grade report for an individual student.
Args:
student (str): The username or identifier of the student.
Updates:
The student's row in `all_student_grades_df` with their weighted average grades.
"""
report = GradeReport(params={"username": student}, display_=False)
row_series = report.weighted_average_grades.transpose().iloc[
0
] # Example transformation
row_series = row_series.reindex(self.all_student_grades_df.columns)
self.all_student_grades_df.loc[student] = row_series
[docs]
def fill_class_grades(self):
"""Populates the class-wide grade report with data from all students.
Iterates through the `student_list` and updates the DataFrame by fetching
and storing each student's weighted average grades.
"""
for student in tqdm.tqdm(self.student_list):
self.update_student_grade(student)
[docs]
def get_class_stats(self):
"""Calculates and stores descriptive statistics for the class-wide grade report.
Requires filling class grades first
"""
# Calculate descriptive statistics
self.stats_df = self.all_student_grades_df.describe(include="all")
[docs]
def write_excel_spreadsheet(self, out_name="output.xlsx"):
"""Exports the class-wide grade report to an Excel spreadsheet.
Args:
out_name (str, optional): Name of output file. Defaults to 'output.xlsx'.
"""
# Export to Excel with different sheets
with pd.ExcelWriter("output.xlsx") as writer:
self.all_student_grades_df.to_excel(writer, sheet_name="all_student_grades")
self.stats_df.to_excel(writer, sheet_name="performance_statistics")
[docs]
def main():
class_grades = ClassGradeReport()
print(class_grades.all_student_grades_df)
if __name__ == "__main__":
main()