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,
24 if assignments is None:
26 self.assignments = sorted(assignments)
29 self.people = sorted(people)
32 self.grades = sorted(grades)
35 def assignment(self, name):
36 for assignment in self.assignments:
37 if assignment.name == name:
39 raise ValueError(name)
41 def active_assignments(self):
42 return sorted(set(grade.assignment for grade in self.grades))
44 def active_groups(self):
46 for person in self.people:
47 groups.update(person.groups)
50 def find_people(self, name=None, email=None, group=None):
51 """Yield ``Person``\s that match ``name``, ``email``, and ``group``
53 The value of ``None`` matches any person.
55 >>> from pygrader.model.person import Person
56 >>> c = Course(people=[
57 ... Person(name='Bilbo Baggins',
58 ... emails=['bb@shire.org', 'bb@greyhavens.net'],
59 ... aliases=['Billy'],
60 ... groups=['students', 'assistants']),
61 ... Person(name='Frodo Baggins',
62 ... emails=['fb@shire.org'],
63 ... groups=['students']),
65 >>> for person in c.find_people(name='Bilbo Baggins'):
67 <Person Bilbo Baggins>
68 >>> for person in c.find_people(name='Billy'):
70 <Person Bilbo Baggins>
71 >>> for person in c.find_people(email='bb@greyhavens.net'):
73 <Person Bilbo Baggins>
74 >>> for person in c.find_people(group='assistants'):
76 <Person Bilbo Baggins>
77 >>> for person in c.find_people(group='students'):
79 <Person Bilbo Baggins>
80 <Person Frodo Baggins>
82 for person in self.people:
83 name_match = (person.name == name or
84 (person.aliases and name in person.aliases))
85 email_match = email in person.emails
86 group_match = group in person.groups
88 for (key,kmatched) in [(name, name_match),
92 if key is not None and not kmatched:
98 def person(self, **kwargs):
99 people = list(self.find_people(**kwargs))
100 assert len(people) == 1, '{} -> {}'.format(kwargs, people)
103 def grade(self, student, assignment):
104 """Return the ``Grade`` that matches ``Student`` and ``Assignment``
106 >>> from pygrader.model.assignment import Assignment
107 >>> from pygrader.model.grade import Grade
108 >>> from pygrader.model.person import Person
109 >>> p = Person(name='Bilbo Baggins')
110 >>> a = Assignment(name='Exam 1')
111 >>> g = Grade(student=p, assignment=a, points=10)
112 >>> c = Course(assignments=[a], people=[p], grades=[g])
113 >>> print(c.grade(student=p, assignment=a))
114 <Grade Bilbo Baggins:Exam 1>
116 for grade in self.grades:
117 if grade.student == student and grade.assignment == assignment:
119 raise ValueError((student, assignment))
121 def total(self, student):
123 for assignment in self.assignments:
125 grade = self.grade(student=student, assignment=assignment)
128 total += float(grade.points)/assignment.points * assignment.weight