34
34
'get_exercise_attempts', 'get_exercise_attempt',
37
def get_exercise_status(store, user, worksheet_exercise, as_of=None):
37
def get_exercise_status(store, user, worksheet_exercise):
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
42
@param worksheet_exercise: An Exercise.
43
@param as_of: Optional datetime. If supplied, gets the status as of as_of.
44
40
Returns a tuple of:
45
41
- A boolean, whether they have successfully passed this exercise.
46
42
- An int, the number of attempts they have made up to and
52
48
is_relevant = ((ExerciseAttempt.user_id == user.id) &
53
49
(ExerciseAttempt.ws_ex_id == worksheet_exercise.id) &
54
50
(ExerciseAttempt.active == True))
56
is_relevant &= ExerciseAttempt.date <= as_of
58
52
# Get the first successful active attempt, or None if no success yet.
59
53
# (For this user, for this exercise).
168
162
saved.date = date
169
163
saved.text = text
171
def calculate_score(store, user, worksheet, as_of=None):
165
def calculate_score(store, user, worksheet):
173
167
Given a storm.store, User, Exercise and Worksheet, calculates a score for
174
168
the user on the given worksheet.
175
@param store: A storm.store
177
@param worksheet: A Worksheet.
178
@param as_of: Optional datetime. If supplied, gets the score as of as_of.
179
169
Returns a 4-tuple of ints, consisting of:
180
170
(No. mandatory exercises completed,
181
171
Total no. mandatory exercises,
193
183
worksheet = worksheet_exercise.worksheet
194
184
optional = worksheet_exercise.optional
196
done, _ = get_exercise_status(store, user, worksheet_exercise, as_of)
186
done, _ = get_exercise_status(store, user, worksheet_exercise)
197
187
# done is a bool, whether this student has completed that problem
205
195
return mand_done, mand_total, opt_done, opt_total
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
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.
225
percent_int = (100 * mand_done) // mand_total
227
# Avoid Div0, just give everyone 0 marks if there are none available
229
# percent / 16, rounded down, with a maximum mark of 5
231
mark = min(percent_int // 16, max_mark)
232
return (percent_int, mark, max_mark)
234
197
def update_exerciselist(worksheet):
235
198
"""Runs through the worksheetstream, generating the appropriate
236
199
WorksheetExercises, and de-activating the old ones."""