1 # Copyright (C) 2012 W. Trevor King <wking@drexel.edu>
3 # This file is part of pygrader.
5 # pygrader is free software: you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation, either version 3 of the License, or (at your option) any later
10 # pygrader is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License along with
15 # pygrader. If not, see <http://www.gnu.org/licenses/>.
17 from .. import LOG as _LOG
20 class Course (object):
21 def __init__(self, name=None, assignments=None, people=None, grades=None):
23 if assignments is None:
25 self.assignments = sorted(assignments)
28 self.people = sorted(people)
31 self.grades = sorted(grades)
33 def assignment(self, name):
34 for assignment in self.assignments:
35 if assignment.name == name:
37 raise ValueError(name)
39 def active_assignments(self):
40 return sorted(set(grade.assignment for grade in self.grades))
42 def active_groups(self):
44 for person in self.people:
45 groups.update(person.groups)
48 def find_people(self, name=None, email=None, group=None):
49 """Yield ``Person``\s that match ``name``, ``email``, and ``group``
51 The value of ``None`` matches any person.
53 >>> from pygrader.model.person import Person
54 >>> c = Course(people=[
55 ... Person(name='Bilbo Baggins',
56 ... emails=['bb@shire.org', 'bb@greyhavens.net'],
57 ... aliases=['Billy'],
58 ... groups=['students', 'assistants']),
59 ... Person(name='Frodo Baggins',
60 ... emails=['fb@shire.org'],
61 ... groups=['students']),
63 >>> for person in c.find_people(name='Bilbo Baggins'):
65 <Person Bilbo Baggins>
66 >>> for person in c.find_people(name='Billy'):
68 <Person Bilbo Baggins>
69 >>> for person in c.find_people(email='bb@greyhavens.net'):
71 <Person Bilbo Baggins>
72 >>> for person in c.find_people(group='assistants'):
74 <Person Bilbo Baggins>
75 >>> for person in c.find_people(group='students'):
77 <Person Bilbo Baggins>
78 <Person Frodo Baggins>
80 for person in self.people:
81 name_match = (person.name == name or
82 (person.aliases and name in person.aliases))
83 email_match = email in person.emails
84 group_match = group in person.groups
86 for (key,kmatched) in [(name, name_match),
90 if key is not None and not kmatched:
96 def person(self, **kwargs):
97 people = list(self.find_people(**kwargs))
98 assert len(people) == 1, '{} -> {}'.format(kwargs, people)
101 def grade(self, student, assignment):
102 """Return the ``Grade`` that matches ``Student`` and ``Assignment``
104 >>> from pygrader.model.assignment import Assignment
105 >>> from pygrader.model.grade import Grade
106 >>> from pygrader.model.person import Person
107 >>> p = Person(name='Bilbo Baggins')
108 >>> a = Assignment(name='Exam 1')
109 >>> g = Grade(student=p, assignment=a, points=10)
110 >>> c = Course(assignments=[a], people=[p], grades=[g])
111 >>> print(c.grade(student=p, assignment=a))
112 <Grade Bilbo Baggins:Exam 1>
114 for grade in self.grades:
115 if grade.student == student and grade.assignment == assignment:
117 raise ValueError((student, assignment))
119 def total(self, student):
121 for assignment in self.assignments:
123 grade = self.grade(student=student, assignment=assignment)
126 total += float(grade.points)/assignment.points * assignment.weight