diff --git a/api/composite_user.py b/api/composite_user.py
index 7036ff6f29cffbb78a116be2b8439b84f92565dd..44fa8ca839136a3a37e6ff3e5420ff9020e62be5 100644
--- a/api/composite_user.py
+++ b/api/composite_user.py
@@ -22,8 +22,11 @@ class CompositeUser:
     graylist: Dict[str, Set[str]]
     blacklist: Set[str]
     candidate_teammates: Set[str]
-    assignments: ClassVar[List[str]] = []  # TODO: make use of this!!
+    # assignments: ClassVar[List[str]] = []  # TODO: make use of this!!
     instances: ClassVar[Dict[str, "CompositeUser"]] = {}
+    basic_fields = ['SortableName', 'ReadableName', 'NUID',
+                    'CanvasUsername', 'CanvasEmail',
+                    'GitlabUsername', 'GitlabEmail', 'Blacklist']
 
     def __init__(self, student_dictionary: Dict[str, str], graylist: Dict[str, Set[str]], blacklist: Collection[str]):
         self.canvas_user: CanvasUser = None
@@ -102,8 +105,9 @@ class CompositeUser:
             else:
                 print(f'Weird. {other}\'s partners for {assignment} '
                       f'are recorded as a {other.graylist[assignment].__class__}')
-        return other.get_canvas_user().get_username() not in my_past_partners and \
-               self.get_canvas_user().get_username() not in your_past_partners
+        i_am_okay = other.get_canvas_user().get_username() not in my_past_partners
+        you_are_okay = self.get_canvas_user().get_username() not in your_past_partners
+        return i_am_okay and you_are_okay
 
     def __repr__(self) -> str:
         if self.canvas_email == self.gitlab_email:
@@ -139,7 +143,7 @@ class CompositeUser:
     def string_to_set(the_string: str) -> Set[str]:
         return set(the_string.split())
 
-    def to_dict(self) -> Dict[str, str]:
+    def to_dict(self, assignments) -> Dict[str, str]:
         student_dictionary = {'SortableName': self.sortable_name.strip(),
                               'ReadableName': self.readable_name.strip(),
                               'NUID': self.NUID,
@@ -148,7 +152,8 @@ class CompositeUser:
                               'GitlabUsername': self.gitlab_username,
                               'GitlabEmail': self.gitlab_email,
                               'Blacklist': CompositeUser.set_to_string(self.blacklist)}
-        # TODO: add assignments
+        for assignment in assignments:
+            student_dictionary[assignment] = CompositeUser.set_to_string(self.graylist[assignment])
         return student_dictionary
 
     # TODO: add CompositeUser.from_dict(Dict[str, str]) -> CompositeUser
@@ -161,8 +166,7 @@ class CompositeUser:
             for csv_student in csv_reader:
                 blacklist: Set[str] = CompositeUser.string_to_set(csv_student['Blacklist'])
                 graylist: Dict[str, Set[str]] = {}
-                handled_fields = {'SortableName', 'ReadableName', 'NUID', 'CanvasUsername', 'CanvasEmail',
-                                  'GitlabUsername', 'GitlabEmail', 'Blacklist'}  # TODO: remove duplication
+                handled_fields = set(CompositeUser.basic_fields)
                 for field in set(csv_student.keys()) - handled_fields:
                     graylist[field] = CompositeUser.string_to_set(csv_student[field])
                 student = CompositeUser(csv_student, graylist, blacklist)
@@ -175,16 +179,14 @@ class CompositeUser:
 
     @staticmethod
     def write_student_csv(students: Set["CompositeUser"], filename: str) -> None:
-        fieldnames = ['SortableName', 'ReadableName', 'NUID',
-                      'CanvasUsername', 'CanvasEmail',
-                      'GitlabUsername', 'GitlabEmail', 'Blacklist']
+        fieldnames = list(CompositeUser.basic_fields)
         random_student = students.pop()
         student_assignments = random_student.graylist.keys()
         students.add(random_student)
         fieldnames.extend(sorted(student_assignments))
         with open(filename, mode='w') as csv_file:
-            fieldnames.extend(CompositeUser.assignments)
+            # fieldnames.extend(CompositeUser.assignments)
             writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
             writer.writeheader()
-            for student in students:
-                writer.writerow(student.to_dict())
+            for student in list(sorted(students, key=lambda s: s.sortable_name)):
+                writer.writerow(student.to_dict(student_assignments))
diff --git a/prep_assignment.py b/prep_assignment.py
index ec07f678a7573b783a16f2d45e49a44320ba3ee4..fddf03047e420084261d07fc0433e321156e7395 100644
--- a/prep_assignment.py
+++ b/prep_assignment.py
@@ -1,6 +1,6 @@
 import random
 import subprocess
-from math import ceil, log10
+# from math import ceil, log10
 from typing import Tuple
 
 from api.canvas_classes import *
@@ -11,13 +11,13 @@ from course import Course
 
 # TODO: assign_partners for arbitrarily-sized teams
 def create_pairs(groupset_name: str = 'Unknown Assignment') -> \
-        List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]]:
+        Tuple[Set[CompositeUser], List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]]]:
     filename: str
     students: Set[CompositeUser]
     file_not_found = True
     while file_not_found:
         try:
-            filename = input('Please provide the name of the file with existing student matches: ')
+            filename = input('Please provide the name of the existing student roster file: ')
             students = CompositeUser.read_student_csv(filename)
             file_not_found = False
         except FileNotFoundError:
@@ -72,7 +72,7 @@ def create_pairs(groupset_name: str = 'Unknown Assignment') -> \
                 if student in preassigned_students:
                     preassigned_students.remove(student)
         elif confirmation.upper()[0] == 'N':
-            print('We\'re not accepting NO for an answer yet. Goodbye.')    # TODO: accept NO for an answer
+            print('We\'re not accepting NO for an answer yet. Goodbye.')  # TODO: accept NO for an answer
             exit(1)
         else:
             print('Aborting.')
@@ -135,10 +135,15 @@ def create_pairs(groupset_name: str = 'Unknown Assignment') -> \
         for student in pair[1:]:
             if student is not None:
                 student.assign_partners(groupset_name, usernames - {student.canvas_username})
-    return student_pairs
+    return students, student_pairs
 
 
-def save_pairs(assignment_number, student_pairs):
+def save_student_roster(students: Set[CompositeUser]):
+    filename = input('Please provide the name of the new student roster file: ')
+    CompositeUser.write_student_csv(students, filename)
+
+
+def create_contact_list(assignment_number, student_pairs):
     filename = f'{assignment_number}-pairs.md'
     with open(filename, mode='w') as pair_file:
         pair_file.write(f'# PARTNERS FOR ASSIGNMENT {assignment_number}\n\n')
@@ -190,10 +195,15 @@ def create_groups(assignment_number, student_pairs):
 
 if __name__ == '__main__':
     groupset: str = input('Please provide the name of the student groupset: ')
-    partners: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]] = create_pairs(groupset)
-    zero_padding = ceil(log10(len(partners)))
-    for partner in partners:
-        print(f'{groupset} {str(partner[0]).zfill(zero_padding)}: {partner[1]}\t{partner[2]}\t{partner[3]}')
+    student_set: Set[CompositeUser]
+    partners: List[Tuple[int, CompositeUser, CompositeUser, Optional[CompositeUser]]]
+    # noinspection PyRedeclaration
+    student_set, partners = create_pairs(groupset)
+    print()
+    save_student_roster(student_set)
+    # zero_padding = ceil(log10(len(partners)))
+    # for partner in partners:
+    #     print(f'{groupset} {str(partner[0]).zfill(zero_padding)}: {partner[1]}\t{partner[2]}\t{partner[3]}')
     """
     assignment = '28'
     pairs = create_pairs('2019-08.csv')