Example #1
0
def get_assignments_by_section(course_id,
                               sections_names=None,
                               assignments_names=None):
    """
    Retrieving assignments by sections.
    """
    # Retrieve the contents of the course
    sections = core_course_get_contents(course_id)

    if sections_names is not None:
        # Filter out section names
        sections = [
            section for section in sections
            if section["name"] not in sections_names
        ]

        found_sections = set(section["name"] for section in sections)
        missing_sections = set(sections_names).difference(found_sections)

        if missing_sections:
            logger.error("Could not find the following sections: %s",
                         list(missing_sections))

    if assignments_names is not None:
        # Handle missing assignments
        found_assignments = set([
            module["name"] for section in sections
            for module in section["modules"]
        ])

        missing_assignments = set(assignments_names).difference(
            found_assignments)
        if missing_assignments:
            logger.error("Could not find the following assignments: %s",
                         missing_assignments)

    assignment_id_to_section = {}

    # Looking through the course contents trying to locate the assignment
    for section in sections:
        for module in section["modules"]:
            # Filter only assignments in moodle
            if module["modname"] != "assign":
                continue

            # Filter assignments by name
            if assignments_names and module["name"] not in assignments_names:
                continue

            assignment_id_to_section[module["id"]] = section["name"]

    assignments = get_assignments(course_id,
                                  list(assignment_id_to_section.keys()))
    assignments_by_section = defaultdict(list)

    for assignment in assignments:
        section_name = assignment_id_to_section[assignment.cmid]
        assignments_by_section[section_name].append(assignment)

    return assignments_by_section
Example #2
0
def status_report(course_id):
    """
    Generates a short report of the students for a specific course.
    Returns a list of StudentStatus tuples.
    """
    assignments = get_assignments(course_id)
    users_map = get_students(course_id)

    submissions_by_user = Counter()
    last_submission_by_user = defaultdict(
        lambda: SubmissionTuple(name="Nothing", timestamp=0))

    for assignment in assignments:
        for submission in assignment.submissions:
            user_name = users_map[submission.user_id]
            submissions_by_user[user_name] += 1

            if (last_submission_by_user[user_name].timestamp <
                    submission.timestamp):
                last_submission_by_user[user_name] = SubmissionTuple(
                    name=assignment.name, timestamp=submission.timestamp)

    student_statuses = []
    for user, submission_count in submissions_by_user.items():
        student_statuses.append(
            StudentStatus(user, submission_count,
                          last_submission_by_user[user].name))

    student_statuses = sorted(
        student_statuses,
        key=lambda student_status: student_status.total_submissions,
    )

    return student_statuses
Example #3
0
def export_submissions(course_id, download_folder):
    """
    Downloads all submissions from a given course
    """
    assignments = get_assignments(course_id)
    users_map = get_students(course_id)
    for assignment in assignments:
        for submission in assignment.submissions:
            download_submission(
                assignment.name,
                users_map[submission.user_id],
                submission,
                download_folder,
            )
Example #4
0
def export_materials(course_id, folder):
    """
    Downloads all the materials from a course to a given folder
    """
    # Put assignments into a dict to find easily
    assigns = {assign.uid: assign for assign in get_assignments(course_id)}
    sections = core_course_get_contents(course_id)

    for section in sections:
        section_folder = Path(folder) / Path(section["name"])
        for module in section["modules"]:
            module_name = module["name"]
            module_type = module["modname"]

            if module_type not in ("resource", "folder", "assign", "url"):
                if module_type not in ["feedback", "forum"]:
                    logger.warning("Skipped export from unknown module '%s'",
                                   module_type)
                continue

            # This is one of the known modules - create the section
            section_folder.mkdir(parents=True, exist_ok=True)

            if module_type in ("resource", "folder"):
                download_folder = section_folder
                # If its a folder, create a subfolder
                if module_type == "folder":
                    download_folder = download_folder / Path(module_name)
                    download_folder.mkdir(parents=True, exist_ok=True)

                for resource in module["contents"]:
                    download_file(resource["fileurl"], download_folder)
            elif module_type == "assign":
                # If module is an assignment - download attachments and description
                assign = assigns[module["instance"]]
                if len(assign.description) > 0:
                    description_file = section_folder / Path(
                        assign.name).with_suffix(".txt")
                    description_file.write_text(assign.description)
                for attachment in assign.attachments:
                    download_file(attachment, section_folder)
            elif module_type == "url":
                url_file = section_folder / Path(f"{module_name}_url.txt")
                # Assuming a url module can only have 1 url inside
                url_file.write_text(module["contents"][0]["fileurl"])
Example #5
0
def submissions_statistics(course_id, is_verbose=False, download_folder=None):
    """
    Returns a dictionary describing the status of ungraded exercises in the course.
    The dictionary looks like this:
        ```
        {
            'total_submissions': 10,
            'total_ungraded': 5,
            'total_resubmissions': 2,
            'exercises': {
                'assign1': {
                    'submissions': 2,
                    'ungraded': 2,
                    'resubmissions': 0}
                },
                ...
            }
        }
        ```

    If download_folder is set, downloads the ungraded exercises
    """
    logger.info("Showing ungraded submissions for course %s", course_id)
    total_submissions = 0
    total_ungraded = 0
    total_resubmissions = 0
    assignments_statistics = {}

    assignments = get_assignments(course_id)
    users_map = get_students(course_id)

    for assignment in assignments:
        current_assignment_submissions_amount = len(assignment.submissions)
        current_assignment_ungraded = assignment.ungraded()
        current_assignment_ungraded_amount = len(current_assignment_ungraded)

        current_assignment_resubmissions_amount = 0
        ungraded_ignored = []

        for submission in current_assignment_ungraded:
            if submission.resubmitted:
                current_assignment_resubmissions_amount += 1

            if submission.user_id in STUDENTS_TO_IGNORE.keys():
                ungraded_ignored.append(STUDENTS_TO_IGNORE[submission.user_id])

            if download_folder is not None:
                download_submission(
                    assignment.name,
                    users_map[submission.user_id],
                    submission,
                    download_folder,
                )

        total_submissions += current_assignment_submissions_amount
        total_ungraded += current_assignment_ungraded_amount
        total_resubmissions += current_assignment_resubmissions_amount

        # Print total stats about this assignment
        if is_verbose and len(ungraded_ignored) != 0:
            logger.info(
                "Ignored %s submissions for assignment '%s' (CMID %s, ID %s): %s",
                len(ungraded_ignored),
                assignment.name,
                assignment.cmid,
                assignment.uid,
                ungraded_ignored,
            )

        amount_ungraded_not_ignored = current_assignment_ungraded_amount - len(
            ungraded_ignored)
        if amount_ungraded_not_ignored != 0:
            logger.info(
                "Total ungraded for assignment [%s] (CMID %s, ID %s): %s/%s",
                assignment.name,
                assignment.cmid,
                assignment.uid,
                amount_ungraded_not_ignored,
                len(assignment.submissions),
            )

        assignments_statistics[assignment.name] = {
            "submissions": current_assignment_submissions_amount,
            "ungraded": amount_ungraded_not_ignored,
            "resubmissions": current_assignment_resubmissions_amount,
        }

    return {
        "total_submissions": total_submissions,
        "total_ungraded": total_ungraded,
        "total_resubmissions": total_resubmissions,
        "exercises": assignments_statistics,
    }