Source code for repobee.ext.pairwise

"""A peer review plugin which attempts to assign pairwise peer reviews.
Intended for students to sit and discuss their code bases with each other, as
well as leave feedback. More specifically, N students are split into N/2
groups, each group member assigned to peer review the other person in the
group.

If N is odd, the students are split into (N-1)/2 groups, in which one group has
3 members.

.. module:: pairwise
    :synopsis: Plugin that provides pairwise peer review allocations.

.. moduleauthor:: Simon Larsén
"""
import random
from typing import Callable, Iterable, Mapping, List

import daiquiri

from repobee_plug import repobee_hook

LOGGER = daiquiri.getLogger(name=__file__)


[docs]@repobee_hook def generate_review_allocations( master_repo_name: str, students: Iterable[str], review_team_name_function: Callable[[str, str], str], num_reviews: int = 1, ) -> Mapping[str, List[str]]: """Generate a (peer_review_team -> reviewers) mapping for each student repository (i.e. <student>-<master_repo_name>), where len(reviewers) = 1 or 2. The ``num_reviews`` argument is ignored by this plugin. Args: master_repo_name: Name of a master repository. students: Students for which to generate peer review allocations. review_team_name_function: A function that takes a master repo name as its first argument, and a student username as its second, and returns a review team name. num_reviews: Ignored by this plugin. Returns: a (peer_review_team -> reviewers) mapping for each student repository. """ students = list(students) if num_reviews != 1: LOGGER.warning( "num_reviews specified to {}, but in pairwise assignment " "num_reviews is ignored".format(num_reviews) ) if len(students) < 2: raise ValueError( "there must be at least 2 students for peer review, " "but {} were provided".format(len(students)) ) random.shuffle(students) groups = [ (students[i - 1], students[i]) for i in range(1, len(students), 2) ] if len(students) % 2: groups[-1] = (*groups[-1], students[-1]) allocations = {} for group in groups: for i, reviewer in enumerate(group): student = group[(i + 1) % len(group)] allocations[ review_team_name_function(student, master_repo_name) ] = [reviewer] return allocations