source: main/waeup.aaue/trunk/src/waeup/aaue/students/studylevel.py @ 13900

Last change on this file since 13900 was 13834, checked in by Henrik Bettermann, 8 years ago

Further customizations for taking the ca into consideration and displaying the ca on all forms and slips.

  • Property svn:keywords set to Id
File size: 5.4 KB
Line 
1## $Id: studylevel.py 13834 2016-04-19 06:42:26Z henrik $
2##
3## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""
19Container which holds the data of a student study level
20and contains the course tickets.
21"""
22import grok
23import pytz
24from datetime import datetime
25from zope.component.interfaces import IFactory
26from zope.component import createObject
27from zope.interface import implementedBy
28from waeup.kofa.utils.helpers import attrs_to_fields
29from waeup.kofa.interfaces import CREATED
30from waeup.kofa.students.studylevel import (
31    StudentStudyLevel, CourseTicket,
32    CourseTicketFactory, StudentStudyLevelFactory)
33from waeup.kofa.students.interfaces import IStudentNavigation
34from waeup.aaue.students.interfaces import (
35    ICustomStudentStudyLevel, ICustomCourseTicket)
36
37
38def getGradeWeightFromScore(score, ca):
39    if None in (score, ca):
40        return (None, None)
41    total = score + ca
42    if total >= 70:
43        return ('A',5)
44    if total >= 60:
45        return ('B',4)
46    if total >= 50:
47        return ('C',3)
48    if total >= 45:
49        return ('D',2)
50    if total >= 40:
51        return ('E',1)
52    return ('F',0)
53
54
55class CustomStudentStudyLevel(StudentStudyLevel):
56    """This is a container for course tickets.
57    """
58    grok.implements(ICustomStudentStudyLevel, IStudentNavigation)
59    grok.provides(ICustomStudentStudyLevel)
60
61    @property
62    def total_credits_s1(self):
63        total = 0
64        for ticket in self.values():
65            if ticket.semester == 1:
66                total += ticket.credits
67        return total
68
69    @property
70    def total_credits_s2(self):
71        total = 0
72        for ticket in self.values():
73            if ticket.semester == 2:
74                total += ticket.credits
75        return total
76
77    @property
78    def gpa_params(self):
79        """Calculate gpa parameters for this level.
80        """
81        credits_weighted = 0.0
82        credits_counted = 0
83        level_gpa = 0.0
84        for ticket in self.values():
85            if None not in (ticket.score, ticket.ca):
86                credits_counted += ticket.credits
87                credits_weighted += ticket.credits * ticket.weight
88        if credits_counted:
89            level_gpa = round(credits_weighted/credits_counted, 3)
90        return level_gpa, credits_counted, credits_weighted
91
92    @property
93    def gpa_params_rectified(self):
94        return self.gpa_params
95
96    @property
97    def course_registration_allowed(self):
98        if self.student.is_fresh:
99            return True
100        try:
101            deadline = grok.getSite()['configuration'][
102                    str(self.level_session)].coursereg_deadline
103        except (TypeError, KeyError):
104            return True
105        if not deadline or deadline > datetime.now(pytz.utc):
106            return True
107        payment_made = False
108        if len(self.student['payments']):
109            for ticket in self.student['payments'].values():
110                if ticket.p_category == 'late_registration' and \
111                    ticket.p_session == self.level_session and \
112                    ticket.p_state == 'paid':
113                        payment_made = True
114        if payment_made:
115            return True
116        return False
117
118CustomStudentStudyLevel = attrs_to_fields(
119    CustomStudentStudyLevel, omit=[
120    'total_credits', 'total_credits_s1', 'total_credits_s2', 'gpa'])
121
122class CustomStudentStudyLevelFactory(StudentStudyLevelFactory):
123    """A factory for student study levels.
124    """
125
126    def __call__(self, *args, **kw):
127        return CustomStudentStudyLevel()
128
129    def getInterfaces(self):
130        return implementedBy(CustomStudentStudyLevel)
131
132class CustomCourseTicket(CourseTicket):
133    """This is a course ticket which allows the
134    student to attend the course. Lecturers will enter scores and more at
135    the end of the term.
136
137    A course ticket contains a copy of the original course and
138    course referrer data. If the courses and/or their referrers are removed, the
139    corresponding tickets remain unchanged. So we do not need any event
140    triggered actions on course tickets.
141    """
142    grok.implements(ICustomCourseTicket, IStudentNavigation)
143    grok.provides(ICustomCourseTicket)
144
145    @property
146    def grade(self):
147        """Returns the grade calculated from score.
148        """
149        return getGradeWeightFromScore(self.score, self.ca)[0]
150
151    @property
152    def weight(self):
153        """Returns the weight calculated from score.
154        """
155        return getGradeWeightFromScore(self.score, self.ca)[1]
156
157CustomCourseTicket = attrs_to_fields(CustomCourseTicket)
158
159class CustomCourseTicketFactory(CourseTicketFactory):
160    """A factory for student study levels.
161    """
162
163    def __call__(self, *args, **kw):
164        return CustomCourseTicket()
165
166    def getInterfaces(self):
167        return implementedBy(CustomCourseTicket)
Note: See TracBrowser for help on using the repository browser.