Skip to content
Snippets Groups Projects
Commit 4e6259c8 authored by Christopher Bohn's avatar Christopher Bohn :thinking:
Browse files

Updated all remaining steps to conform to new design

parent 1c4457ee
No related branches found
No related tags found
No related merge requests found
import random import random
import subprocess import subprocess
# from math import ceil, log10 from math import ceil, log10
from typing import Tuple from typing import Tuple
from api.canvas_classes import * from api.canvas_classes import *
...@@ -24,6 +24,7 @@ def get_students() -> Set[CompositeUser]: ...@@ -24,6 +24,7 @@ def get_students() -> Set[CompositeUser]:
# TODO: assign_partners for arbitrarily-sized teams # TODO: assign_partners for arbitrarily-sized teams
# TODO: break this up into bite-sized chunks
def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Assignment') -> \ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Assignment') -> \
List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]]: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]]:
students_with_blacklist: Set[CompositeUser] = sorted(list(filter(lambda s: s.has_blacklist(), students)), students_with_blacklist: Set[CompositeUser] = sorted(list(filter(lambda s: s.has_blacklist(), students)),
...@@ -35,12 +36,31 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass ...@@ -35,12 +36,31 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass
if groupset_name in fields: if groupset_name in fields:
preassigned_students = set(filter(lambda s: len(s.graylist[groupset_name]) > 0, students)) preassigned_students = set(filter(lambda s: len(s.graylist[groupset_name]) > 0, students))
unassigned_students: Set[CompositeUser] = set(students) unassigned_students: Set[CompositeUser] = set(students)
# handle student excusals
excused_students = set(filter(lambda s: s.graylist[groupset_name] == set('X'), preassigned_students))
# noinspection PyUnusedLocal
confirmation: str
# noinspection PyUnusedLocal
student: CompositeUser
for student in excused_students:
confirmation = input(f'\tExclude {student.readable_name} from student pairing ([Yes]/No/Abort)? ')
if confirmation == "" or confirmation.upper()[0] == 'Y':
print(f'Removing {student.readable_name} from pre-assigned students and from unassigned students.')
preassigned_students.remove(student)
unassigned_students.remove(student)
student.graylist[groupset_name] = set()
elif confirmation.upper()[0] == 'N':
print(f'Removing {student.readable_name} from pre-assigned students but leaving in unassigned students.')
preassigned_students.remove(student)
student.graylist[groupset_name] = set()
else:
print('Aborting.')
exit(0)
# handle truly-preassigned students
pair_number: int = 0 pair_number: int = 0
student_pairs: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]] = [] student_pairs: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]] = []
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
potential_pair: List[CompositeUser] potential_pair: List[CompositeUser]
# noinspection PyUnusedLocal
confirmation: str
if preassigned_students: if preassigned_students:
print('First we shall confirm pre-assigned partners.') print('First we shall confirm pre-assigned partners.')
else: else:
...@@ -52,7 +72,7 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass ...@@ -52,7 +72,7 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass
potential_pair = [] potential_pair = []
pair_number += 1 pair_number += 1
print(f'Preparing pair {pair_number}...') print(f'Preparing pair {pair_number}...')
student: CompositeUser = preassigned_students.pop() student = preassigned_students.pop()
potential_pair.append(pair_number) potential_pair.append(pair_number)
potential_pair.append(student) potential_pair.append(student)
potential_partners: Set[str] = student.graylist[groupset_name] potential_partners: Set[str] = student.graylist[groupset_name]
...@@ -120,9 +140,10 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass ...@@ -120,9 +140,10 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass
print('Very finally, we shall now assign the odd student to an existing partnership.') print('Very finally, we shall now assign the odd student to an existing partnership.')
match_found = False match_found = False
while not match_found: while not match_found:
pair_number -= 1
potential_partners: Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]] = \ potential_partners: Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]] = \
student_pairs[--pair_number] student_pairs[pair_number]
if potential_partners[2] is None and \ if potential_partners[3] is None and \
odd_student.is_graylist_compatible(potential_partners[1]) and \ odd_student.is_graylist_compatible(potential_partners[1]) and \
odd_student.is_graylist_compatible(potential_partners[2]) and \ odd_student.is_graylist_compatible(potential_partners[2]) and \
odd_student.is_blacklist_compatible(potential_partners[1]) and \ odd_student.is_blacklist_compatible(potential_partners[1]) and \
...@@ -134,6 +155,7 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass ...@@ -134,6 +155,7 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass
f'{potential_partners[1].readable_name} and {potential_partners[2].readable_name}') f'{potential_partners[1].readable_name} and {potential_partners[2].readable_name}')
else: else:
print('There is no odd student to add to an existing partnership.') print('There is no odd student to add to an existing partnership.')
# update graylists
for pair in student_pairs: for pair in student_pairs:
usernames = set(map(lambda s: s.canvas_username if isinstance(s, CompositeUser) else None, pair)) - {None} usernames = set(map(lambda s: s.canvas_username if isinstance(s, CompositeUser) else None, pair)) - {None}
for student in pair[1:]: for student in pair[1:]:
...@@ -142,83 +164,81 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass ...@@ -142,83 +164,81 @@ def create_pairs(students: Set[CompositeUser], groupset_name: str = 'Unknown Ass
return student_pairs return student_pairs
def save_student_roster(students: Set[CompositeUser]): def save_student_roster(students: Set[CompositeUser]) -> None:
filename = input('Please provide the name of the new student roster file: ') filename = input('Please provide the name of the new student roster file: ')
print(f'Writing {filename}.')
CompositeUser.write_student_csv(students, filename) CompositeUser.write_student_csv(students, filename)
def create_contact_list(assignment_number, student_pairs): def create_contact_list(groupset_name: str,
filename = f'{assignment_number}-pairs.md' student_pairs: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]]) -> None:
filename = f'{groupset_name}-partners.md'
print(f'Writing {filename}.')
zero_padding: int = ceil(log10(len(partners)))
with open(filename, mode='w') as pair_file: with open(filename, mode='w') as pair_file:
pair_file.write(f'# PARTNERS FOR ASSIGNMENT {assignment_number}\n\n') pair_file.write(f'# PARTNERS FOR ASSIGNMENT {groupset_name}\n\n')
for pair in student_pairs: for pair in student_pairs:
pair_file.write(f'- {assignment_number}pair {pair[0]}\n') pair_file.write(f'- {groupset_name} {str(pair[0]).zfill(zero_padding)}\n')
pair_file.write(f' - {pair[1]}\n') pair_file.write(f' - {pair[1]}\n')
pair_file.write(f' - {pair[2]}\n') pair_file.write(f' - {pair[2]}\n')
if pair[3] is not None: if pair[3] is not None:
pair_file.write(f' - {pair[3]}\n') pair_file.write(f' - {pair[3]}\n')
def create_repositories(assignment_number, student_pairs, verbose): def create_repositories(groupset_name: str,
if verbose: student_pairs: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]]) -> None:
print('Creating file for clone script.') filename = f'{groupset_name}-clone.sh'
filename = f'{assignment_number}-clone.sh' print(f'Creating file for clone script: {filename}. Creating repositories on Gitlab.')
zero_padding: int = ceil(log10(len(partners)))
with open(filename, mode='w') as clone_file: with open(filename, mode='w') as clone_file:
clone_file.write('#!/bin/bash\n\n') clone_file.write('#!/bin/bash\n\n')
clone_file.write('# Auto-generated clone script.\n') clone_file.write('# Auto-generated clone script.\n')
for pair in student_pairs: for pair in student_pairs:
if verbose: print(f'\tCreating repo for pair number {str(pair[0]).zfill(zero_padding)}')
print(f'Creating repo for pair number {pair[0]}')
project = GitlabProject.create_project_in_group(Course.gitlab_namespace, project = GitlabProject.create_project_in_group(Course.gitlab_namespace,
f'{assignment_number}pair{pair[0]}') f'{groupset_name}{str(pair[0]).zfill(zero_padding)}')
if verbose: print(f'\t\tAdding {pair[1]}')
print(f'\tAdding {pair[1]}')
project.add_user_as_maintainer(pair[1].get_gitlab_user()) project.add_user_as_maintainer(pair[1].get_gitlab_user())
if verbose: print(f'\t\tAdding {pair[2]}')
print(f'\tAdding {pair[2]}')
project.add_user_as_maintainer(pair[2].get_gitlab_user()) project.add_user_as_maintainer(pair[2].get_gitlab_user())
if pair[3] is not None: if pair[3] is not None:
if verbose: print(f'\t\tAdding {pair[3]}')
print(f'\tAdding {pair[3]}')
project.add_user_as_maintainer(pair[3].get_gitlab_user()) project.add_user_as_maintainer(pair[3].get_gitlab_user())
repo_url = project.get_cloning_url() repo_url = project.get_cloning_url()
clone_file.write(f'git clone {repo_url}\n') clone_file.write(f'git clone {repo_url}\n')
subprocess.call(['chmod', '+x', filename]) subprocess.call(['chmod', '+x', filename])
print('Repositories created')
def create_groups(assignment_number, student_pairs): def create_groups(groupset_name: str,
student_pairs: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]]) -> None:
print(f'Creating groupset {groupset_name} and student groups on Canvas.')
course = CanvasCourse(Course.canvas_course_id) course = CanvasCourse(Course.canvas_course_id)
group_set = course.create_user_groupset(f'{assignment_number}pairs') group_set = course.create_user_groupset(groupset_name)
zero_padding: int = ceil(log10(len(partners)))
for pair in student_pairs: for pair in student_pairs:
group = group_set.create_group(f'{assignment_number}pair {pair[0]}') group = group_set.create_group(f'\t{groupset_name} {str(pair[0]).zfill(zero_padding)}')
group.add_student(pair[1].get_canvas_user()) group.add_student(pair[1].get_canvas_user())
group.add_student(pair[2].get_canvas_user()) group.add_student(pair[2].get_canvas_user())
if pair[3] is not None: if pair[3] is not None:
group.add_student(pair[3].get_canvas_user()) group.add_student(pair[3].get_canvas_user())
print('Canvas groups created')
if __name__ == '__main__': if __name__ == '__main__':
groupset: str = input('Please provide the name of the student groupset: ') groupset: str = input('Please provide the name of the student groupset: ')
student_set: Set[CompositeUser] = get_students() student_set: Set[CompositeUser] = get_students()
# TODO: check for changes to course roster
# TODO: check for changes to gitlab usernames
partners: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]] = create_pairs(student_set, partners: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]] = create_pairs(student_set,
groupset) groupset)
print() print()
save_student_roster(student_set) save_student_roster(student_set)
# zero_padding = ceil(log10(len(partners))) create_contact_list(groupset, partners)
# for partner in partners: print()
# print(f'{groupset} {str(partner[0]).zfill(zero_padding)}: {partner[1]}\t{partner[2]}\t{partner[3]}') create_repositories(groupset, partners)
""" print()
assignment = '28' create_groups(groupset, partners)
pairs = create_pairs('2019-08.csv') print()
save_pairs(assignment, pairs)
print('Pairs created')
create_repositories(assignment, pairs, True)
print('Repositories created')
create_groups(assignment, pairs)
print('Canvas groups created')
print('TODO:\tAdd issues') print('TODO:\tAdd issues')
print('\tCommit starter code') print('\tCommit starter code')
print('\tUpdate graylists (also, please update the code to update the graylists)')
"""
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment