""" A Grader grades a WhatToGrade (e.g. a Session, Module in a Session, Function in a Module, ...), for each username in Students, using a: -- Getter (to get the data needed to grade) -- Tester (to run tests that form the result of the Grader's grading) -- Recorder (to record the results of the tests) Authors: David Mutchler, David Lam, Mark Hays and their colleagues. Version 2.0: March, 2021. """ from WhatToGrade import WhatToGrade, StandardWhatToGrade from WhoToGrade import WhoToGrade, StandardWhoToGrade from Getter import Getter, StandardGetter from Tester import Tester, StandardTester from Recorder import Recorder, StandardRecorder class Grader: """ Grades a Session, Module, Function, ... for a list of Students """ def __init__(self, what_to_grade: WhatToGrade = None, who_to_grade: WhoToGrade = None, getter: Getter = None, tester: Tester = None, recorder: Recorder = None): if not what_to_grade: what_to_grade = WhatToGrade() if not who_to_grade: who_to_grade = WhoToGrade() if not getter: getter = Getter(what_to_grade, who_to_grade) if not tester: tester = Tester(what_to_grade, who_to_grade) if not recorder: recorder = Recorder(what_to_grade, who_to_grade) self.what_to_grade = what_to_grade self.who_to_grade = who_to_grade self.getter = getter self.tester = tester self.recorder = recorder def grade(self): self.getter.get() results = self.tester.test() self.recorder.record(results) # # 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)