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, assignments=None, people=None, grades=None):
22 if assignments is None:
24 self.assignments = sorted(assignments)
27 self.people = sorted(people)
30 self.grades = sorted(grades)
32 def assignment(self, name):
33 for assignment in self.assignments:
34 if assignment.name == name:
36 raise ValueError(name)
38 def active_assignments(self):
39 return sorted(set(grade.assignment for grade in self.grades))
41 def active_groups(self):
43 for person in self.people:
44 groups.update(person.groups)
47 def find_people(self, name=None, email=None, group=None):
48 """Yield ``Person``\s that match ``name``, ``email``, and ``group``
50 The value of ``None`` matches any person.
52 >>> from pygrade.model.person import Person
53 >>> c = Course(people=[
54 ... Person(name='Bilbo Baggins',
55 ... emails=['bb@shire.org', 'bb@greyhavens.net'],
56 ... aliases=['Billy'],
57 ... groups=['students', 'assistants']),
58 ... Person(name='Frodo Baggins',
59 ... emails=['fb@shire.org'],
60 ... groups=['students']),
62 >>> for person in c.find_people(name='Bilbo Baggins'):
64 <Person Bilbo Baggins>
65 >>> for person in c.find_people(name='Billy'):
67 <Person Bilbo Baggins>
68 >>> for person in c.find_people(email='bb@greyhavens.net'):
70 <Person Bilbo Baggins>
71 >>> for person in c.find_people(group='assistants'):
73 <Person Bilbo Baggins>
74 >>> for person in c.find_people(group='students'):
76 <Person Bilbo Baggins>
77 <Person Frodo Baggins>
79 for person in self.people:
80 name_match = (person.name == name or
81 (person.aliases and name in person.aliases))
82 email_match = email in person.emails
83 group_match = group in person.groups
85 for (key,kmatched) in [(name, name_match),
89 if key is not None and not kmatched:
95 def person(self, **kwargs):
96 people = list(self.find_people(**kwargs))
97 assert len(people) == 1, '{} -> {}'.format(kwargs, people)
100 def grade(self, student, assignment):
101 """Return the ``Grade`` that matches ``Student`` and ``Assignment``
103 >>> from pygrade.model.assignment import Assignment
104 >>> from pygrade.model.grade import Grade
105 >>> from pygrade.model.person import Person
106 >>> p = Person(name='Bilbo Baggins')
107 >>> a = Assignment(name='Exam 1')
108 >>> g = Grade(student=p, assignment=a, points=10)
109 >>> c = Course(assignments=[a], people=[p], grades=[g])
110 >>> print(c.grade(student=p, assignment=a))
111 <Grade Bilbo Baggins:Exam 1>
113 for grade in self.grades:
114 if grade.student == student and grade.assignment == assignment:
116 raise ValueError((student, assignment))
118 def total(self, student):
120 for assignment in self.assignments:
122 grade = self.grade(student=student, assignment=assignment)
125 total += float(grade.points)/assignment.points * assignment.weight