~azzar1/unity/add-show-desktop-key

« back to all changes in this revision

Viewing changes to ivle/worksheet/utils.py

  • Committer: William Grant
  • Date: 2009-04-28 08:25:30 UTC
  • Revision ID: grantw@unimelb.edu.au-20090428082530-u6w762gn0cyokpwf
Remove ivle.conf dependency from ivle.webapp.filesystem.serve.

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
           'get_exercise_attempts', 'get_exercise_attempt',
35
35
          ]
36
36
 
37
 
def get_exercise_status(store, user, worksheet_exercise):
 
37
def get_exercise_status(store, user, worksheet_exercise, as_of=None):
38
38
    """Given a storm.store, User and Exercise, returns information about
39
39
    the user's performance on that problem.
 
40
    @param store: A storm.store
 
41
    @param user: A User.
 
42
    @param worksheet_exercise: An Exercise.
 
43
    @param as_of: Optional datetime. If supplied, gets the status as of as_of.
40
44
    Returns a tuple of:
41
45
        - A boolean, whether they have successfully passed this exercise.
42
46
        - An int, the number of attempts they have made up to and
48
52
    is_relevant = ((ExerciseAttempt.user_id == user.id) &
49
53
            (ExerciseAttempt.ws_ex_id == worksheet_exercise.id) &
50
54
            (ExerciseAttempt.active == True))
 
55
    if as_of is not None:
 
56
        is_relevant &= ExerciseAttempt.date <= as_of
51
57
 
52
58
    # Get the first successful active attempt, or None if no success yet.
53
59
    # (For this user, for this exercise).
162
168
    saved.date = date
163
169
    saved.text = text
164
170
 
165
 
def calculate_score(store, user, worksheet):
 
171
def calculate_score(store, user, worksheet, as_of=None):
166
172
    """
167
173
    Given a storm.store, User, Exercise and Worksheet, calculates a score for
168
174
    the user on the given worksheet.
 
175
    @param store: A storm.store
 
176
    @param user: A User.
 
177
    @param worksheet: A Worksheet.
 
178
    @param as_of: Optional datetime. If supplied, gets the score as of as_of.
169
179
    Returns a 4-tuple of ints, consisting of:
170
180
    (No. mandatory exercises completed,
171
181
     Total no. mandatory exercises,
183
193
        worksheet = worksheet_exercise.worksheet
184
194
        optional = worksheet_exercise.optional
185
195
 
186
 
        done, _ = get_exercise_status(store, user, worksheet_exercise)
 
196
        done, _ = get_exercise_status(store, user, worksheet_exercise, as_of)
187
197
        # done is a bool, whether this student has completed that problem
188
198
        if optional:
189
199
            opt_total += 1
194
204
 
195
205
    return mand_done, mand_total, opt_done, opt_total
196
206
 
 
207
def calculate_mark(mand_done, mand_total):
 
208
    """Calculate a subject mark, given the result of all worksheets.
 
209
    @param mand_done: The total number of mandatory exercises completed by
 
210
        some student, across all worksheets.
 
211
    @param mand_total: The total number of mandatory exercises across all
 
212
        worksheets in the offering.
 
213
    @return: (percent, mark, mark_total)
 
214
        percent: The percentage of exercises the student has completed, as an
 
215
            integer between 0 and 100 inclusive.
 
216
        mark: The mark the student has received, based on the percentage.
 
217
        mark_total: The total number of marks available (currently hard-coded
 
218
            as 5).
 
219
    """
 
220
    # We want to display a students mark out of 5. However, they are
 
221
    # allowed to skip 1 in 5 questions and still get 'full marks'.
 
222
    # Hence we divide by 16, essentially making 16 percent worth
 
223
    # 1 star, and 80 or above worth 5.
 
224
    if mand_total > 0:
 
225
        percent_int = (100 * mand_done) // mand_total
 
226
    else:
 
227
        # Avoid Div0, just give everyone 0 marks if there are none available
 
228
        percent_int = 0
 
229
    # percent / 16, rounded down, with a maximum mark of 5
 
230
    max_mark = 5
 
231
    mark = min(percent_int // 16, max_mark)
 
232
    return (percent_int, mark, max_mark)
 
233
 
197
234
def update_exerciselist(worksheet):
198
235
    """Runs through the worksheetstream, generating the appropriate
199
236
    WorksheetExercises, and de-activating the old ones."""
200
237
    exercises = []
201
238
    # Turns the worksheet into an xml stream, and then finds all the 
202
239
    # exercise nodes in the stream.
203
 
    worksheetdata = genshi.XML(worksheet.data)
 
240
    worksheetdata = genshi.XML(worksheet.get_xml())
204
241
    for kind, data, pos in worksheetdata:
205
242
        if kind is genshi.core.START:
206
243
            # Data is a tuple of tag name and a list of name->value tuples