# FIXME: This file needs to be reworked!!!!!!!!! """ A Grader grades the WhoToGrade in a WhatToGrade, using a: -- HowToGrade -- Recorder -- RepoHelper (for checking out files). Authors: David Mutchler, David Lam, Mark Hays and their colleagues. Version 1.2: March, 2017. """ from recorder import StandardRecorder from repoHelper import StandardRepoHelper from howToGrade import StandardHowToGrade from whoToGrade import StandardWhoToGrade class Grader(object): """ A Grader grades the WhoToGrade in a WhatToGrade, using a: -- HowToGrade -- Recorder -- RepoHelper (for checking out files). :type what_to_grade: WhatToGrade :type this_who_to_grade: WhoToGrade :type this_how_to_grade: HowToGrade :type this_recorder: Recorder :type this_repo_helper: RepoHelper """ def __init__(self, what_to_grade, this_who_to_grade=None, this_how_to_grade=None, this_recorder=None, this_repo_helper=None): self.what_to_grade = what_to_grade course = what_to_grade.course self.who_to_grade = (this_who_to_grade or StandardWhoToGrade(course)) self.repo_helper = (this_repo_helper or StandardRepoHelper(what_to_grade)) how = (this_how_to_grade or StandardHowToGrade) self.how_to_grade = how(self.what_to_grade, self.who_to_grade, self.repo_helper) self.recorder = this_recorder or StandardRecorder() def grade(self, force_checkout=False, display_results=True): """ Do the grading. """ # Checkout: checkout = self.repo_helper.checkout_for_grading # Abbreviation result = checkout(self.what_to_grade, self.who_to_grade.students, force_checkout) if display_results: self._display_result_of_checkout(result) # Grade: results = self.how_to_grade.do_tests() # Record: # # Checkout the original and solution projects: # if include_original: # original = self.what_to_grade.course.username_for_original # self.repoHelper.checkout_for_grading(what, [original]) # # if include_solution: # solution = self.what_to_grade.course.username_for_solution # self.repoHelper.checkout_for_grading(what, [solution]) # # # Do the tests on the specified students (usernames) # # and record the results: # results = self.howToGrade.do_tests_on_students() # self.recorder.record_all_results(results) # print('Failures:') # self.recorder.record_failures(results) @staticmethod def _display_result_of_checkout(result): """ Display the given result, which is a 2-tuple containing: -- the list of failed checkouts -- the list of skipped checkouts :type result: tuple(list(str)) """ failures, skipped, _ = result # Ignore the 3rd item: successes if failures: print('\nCheckout FAILED for the following students:') print(' ', *failures, sep=' ') if skipped: print('\nCheckout SKIPPED the following students') print('because their projects were already checked out:') print(' ', *skipped, sep=' ') class ProjectGrader(Grader): # TODO: Move the part of Grader (above) that is specific to # grading a project to this class. # CONSIDER: Should a ProjectGrader use ModuleGraders? def __init__(self, what_to_grade): """ :type what_to_grade: ThingToGrade """ super().__init__(what_to_grade) class ModuleGrader(Grader): # CONSIDER: Is this subclass a good thing to implement? # If so, implement this. pass class FunctionGrader(Grader): # CONSIDER: Is this subclass a good thing to implement? # If so, implement this. pass class StandardGrader(ProjectGrader): """ A StandardGrader is a ProjectGrader that uses a StandardTester and StandardRecorder to grade all students in the ThingToGrade's Course. """ def __init__(self, what_to_grade): """ :type what_to_grade: ThingToGrade """ super().__init__(what_to_grade) # ---------------------------------------------------------------------- # Code below here was once useful but is no longer correct. # # CONSIDER: Maybe rejuventate it. # ---------------------------------------------------------------------- # def choose_testers(self): # for thing_to_grade in self.things_to_grade: # self.howToGrade[thing_to_grade] = howToGrade.Tester(thing_to_grade) # # (self.grader[thing_to_grade]).grade(thing_to_grade) # if not self.students_to_grade: # self.get_students_to_grade() # if not self.thing_to_grade: # self.get_thing_to_grade() # results = [] # for student in self.thing_to_grade.students: # for howToGrade in self.testers: # result = howToGrade.run_tests(self.thing_to_grade, student) # results.append(result) # self.recorder.record(results) # class ThingToGrade: # """ # Something to be graded: # -- A project, or a module in the project, or a function # in a module in the project, or a collection of these, # along with # -- a list of students (usernames, or perhaps team names) # whose submissions are to be graded. # """ # def __init__(self, # name_of_thing_to_grade=None, course=None, term=None) # """ # If the thing_to_grade is: # -- a list => grade all the things in the list # -- a number N => grade all of the Session N project # -- a (N, M) pair => grade module M in the Session N project # -- a (N, M, s) triple => grade function s in module M # in the Session N project # -- ... # """ # # # TODO: Handle situations other than the above. # self.parse_name(name_of_thing_to_grade) # self.course = course if course else self.default_course() # self.term = term if term else self.current_term() # # # def parse_name(self, name_of_thing_to_grade): # # All these can be a list # self.session # 1, 2, ... # self.project # Session01_..., Session02_..., ... # self.modules # # def default_course(self): # # TODO: Get from a defaults.txt file. # return 'csse120' # # def current_term(self): # # TODO: Use the current date. # return '201510' # # # def all_students(self): # return # # self.students = students # self.function_name = function_name # if recheckout: # self.checkout(True) # # def checkout(self, overwrite=False): # svn.checkout(self.project, self.students)