31
31
'get_exercise_attempts', 'get_exercise_attempt',
34
def get_exercise_status(store, user, worksheet_exercise):
34
def get_exercise_status(store, user, exercise, worksheet):
35
35
"""Given a storm.store, User and Exercise, returns information about
36
36
the user's performance on that problem.
37
37
Returns a tuple of:
43
43
# A Storm expression denoting all active attempts by this user for this
45
45
is_relevant = ((ExerciseAttempt.user_id == user.id) &
46
(ExerciseAttempt.ws_ex_id == worksheet_exercise.id) &
47
(ExerciseAttempt.active == True))
46
(ExerciseAttempt.exercise_id == exercise.id) &
47
(ExerciseAttempt.active == True) &
48
(ExerciseAttempt.worksheetid == worksheet.id))
49
50
# Get the first successful active attempt, or None if no success yet.
50
51
# (For this user, for this exercise).
67
68
return first_success is not None, num_attempts
69
def get_exercise_stored_text(store, user, worksheet_exercise):
70
"""Given a storm.store, User and WorksheetExercise, returns an
70
def get_exercise_stored_text(store, user, exercise, worksheet):
71
"""Given a storm.store, User and Exercise, returns an
71
72
ivle.database.ExerciseSave object for the last saved/submitted attempt for
72
73
this question (note that ExerciseAttempt is a subclass of ExerciseSave).
73
74
Returns None if the user has not saved or made an attempt on this
79
80
# Get the saved text, or None
80
81
saved = store.find(ExerciseSave,
81
82
ExerciseSave.user_id == user.id,
82
ExerciseSave.ws_ex_id == worksheet_exercise.id).one()
83
ExerciseSave.exercise_id == exercise.id,
84
ExerciseSave.worksheetid == worksheet.id).one()
84
86
# Get the most recent attempt, or None
85
87
attempt = store.find(ExerciseAttempt,
86
88
ExerciseAttempt.user_id == user.id,
89
ExerciseAttempt.exercise_id == exercise.id,
90
ExerciseAttempt.worksheetid == worksheet.id,
87
91
ExerciseAttempt.active == True,
88
ExerciseAttempt.ws_ex_id == worksheet_exercise.id
89
92
).order_by(Asc(ExerciseAttempt.date)).last()
91
94
# Pick the most recent of these two
103
def _get_exercise_attempts(store, user, worksheet_exercise, as_of=None,
106
def _get_exercise_attempts(store, user, exercise, worksheet, as_of=None,
104
107
allow_inactive=False):
105
108
"""Same as get_exercise_attempts, but doesn't convert Storm's iterator
108
111
# Get the most recent attempt before as_of, or None
109
112
return store.find(ExerciseAttempt,
110
113
ExerciseAttempt.user_id == user.id,
111
ExerciseAttempt.ws_ex_id == worksheet_exercise.id,
114
ExerciseAttempt.exercise_id == exercise.id,
115
ExerciseAttempt.worksheetid == worksheet.id,
112
116
True if allow_inactive else ExerciseAttempt.active == True,
113
117
True if as_of is None else ExerciseAttempt.date <= as_of,
114
118
).order_by(Desc(ExerciseAttempt.date))
116
def get_exercise_attempts(store, user, worksheet_exercise, as_of=None,
120
def get_exercise_attempts(store, user, exercise, worksheet, as_of=None,
117
121
allow_inactive=False):
118
122
"""Given a storm.store, User and Exercise, returns a list of
119
123
ivle.database.ExerciseAttempt objects, one for each attempt made for the
123
127
attempts made before or at this time.
124
128
allow_inactive: If True, will return disabled attempts.
126
return list(_get_exercise_attempts(store, user, worksheet_exercise, as_of,
130
return list(_get_exercise_attempts(store, user, exercise, worksheet, as_of,
129
def get_exercise_attempt(store, user, worksheet_exercise, as_of=None,
133
def get_exercise_attempt(store, user, exercise, worksheet, as_of=None,
130
134
allow_inactive=False):
131
"""Given a storm.store, User and WorksheetExercise, returns an
135
"""Given a storm.store, User and Exercise, returns an
132
136
ivle.database.ExerciseAttempt object for the last submitted attempt for
134
138
Returns None if the user has not made an attempt on this
138
142
attempts made before or at this time.
139
143
allow_inactive: If True, will return disabled attempts.
141
return _get_exercise_attempts(store, user, worksheet_exercise, as_of,
145
return _get_exercise_attempts(store, user, exercise, worksheet, as_of,
142
146
allow_inactive).first()
144
def save_exercise(store, user, worksheet_exercise, text, date):
148
def save_exercise(store, user, exercise, worksheet, text, date):
145
149
"""Save an exercise for a user.
147
Given a store, User, WorksheetExercise, text and date, save the text to the
151
Given a store, User, Exercise and text and date, save the text to the
148
152
database. This will create the ExerciseSave if needed.
150
154
saved = store.find(ivle.database.ExerciseSave,
151
155
ivle.database.ExerciseSave.user_id == user.id,
152
ivle.database.ExerciseSave.ws_ex_id == worksheet_exercise.id
156
ivle.database.ExerciseSave.exercise_id == exercise.id,
157
ivle.database.ExerciseSave.worksheetid == worksheet.id
154
159
if saved is None:
155
saved = ivle.database.ExerciseSave(user=user,
156
worksheet_exercise=worksheet_exercise)
160
saved = ivle.database.ExerciseSave(user=user, exercise=exercise,
159
164
saved.date = date
180
185
worksheet = worksheet_exercise.worksheet
181
186
optional = worksheet_exercise.optional
183
done, _ = get_exercise_status(store, user, worksheet_exercise)
188
done, _ = get_exercise_status(store, user, exercise, worksheet)
184
189
# done is a bool, whether this student has completed that problem