1
# IVLE - Informatics Virtual Learning Environment
2
# Copyright (C) 2007-2009 The University of Melbourne
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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
from storm.locals import Store
22
from ivle.database import (Exercise, ExerciseAttempt, Offering, User,
23
Worksheet, WorksheetExercise)
25
from ivle.webapp import ApplicationRoot
26
from ivle.webapp.publisher import ROOT
27
from ivle.webapp.publisher.decorators import forward_route, reverse_route
31
from ivle.webapp.tutorial.service import TIMESTAMP_FORMAT
33
# If True, getattempts or getattempt will allow browsing of inactive/disabled
34
# attempts. If False, will not allow this.
35
HISTORY_ALLOW_INACTIVE = False
37
@forward_route(ApplicationRoot, '+exercises', argc=1)
38
def root_to_exercise(root, exercise_name):
39
return root.store.find(
41
Exercise.id == exercise_name
44
@reverse_route(Exercise)
45
def exercise_url(exercise):
46
return (ROOT, ('+exercises', exercise.id))
49
@forward_route(Offering, '+worksheets', argc=1)
50
def offering_to_worksheet(offering, worksheet_name):
51
return Store.of(offering).find(
53
Worksheet.offering == offering,
54
Worksheet.identifier == worksheet_name
57
@reverse_route(Worksheet)
58
def worksheet_url(worksheet):
59
return (worksheet.offering, ('+worksheets', worksheet.identifier))
62
@forward_route(Worksheet, argc=1)
63
def worksheet_to_worksheetexercise(worksheet, exercise_name):
64
return Store.of(worksheet).find(
66
WorksheetExercise.exercise_id == exercise_name,
67
WorksheetExercise.worksheet == worksheet
70
@reverse_route(WorksheetExercise)
71
def worksheetexercise_url(worksheetexercise):
72
return (worksheetexercise.worksheet,
73
worksheetexercise.exercise.identifier)
76
class ExerciseAttempts(object):
77
"""The set of exercise attempts for a user and exercise.
79
A combination of a User and WorksheetExercise, this provides access to
80
the User's ExerciseAttempts.
83
def __init__(self, worksheet_exercise, user):
84
self.worksheet_exercise = worksheet_exercise
87
def get_permissions(self, user, config):
88
return self.user.get_permissions(user, config)
91
@forward_route(WorksheetExercise, '+attempts', argc=1)
92
def worksheetexercise_to_exerciseattempts(worksheet_exercise, login):
93
user = User.get_by_login(Store.of(worksheet_exercise), login)
96
return ExerciseAttempts(worksheet_exercise, user)
98
@reverse_route(ExerciseAttempts)
99
def exerciseattempts_url(exerciseattempts):
100
return (exerciseattempts.worksheet_exercise,
101
('+attempts', exerciseattempts.user.login))
104
@forward_route(ExerciseAttempts, argc=1)
105
def exerciseattempts_to_attempt(exercise_attempts, date):
107
date = datetime.datetime.strptime(date, TIMESTAMP_FORMAT)
111
# XXX Hack around Google Code issue #87
112
# Query from the given date +1 secnod.
113
# Date is in seconds (eg. 3:47:12), while the data is in finer time
114
# (eg. 3:47:12.3625). The query "date <= 3:47:12" will fail because
115
# 3:47:12.3625 is greater. Hence we do the query from +1 second,
116
# "date <= 3:47:13", and it finds the correct submission, UNLESS there
117
# are multiple submissions inside the same second.
118
date += datetime.timedelta(seconds=1)
120
return ivle.worksheet.utils.get_exercise_attempt(
121
Store.of(exercise_attempts.user),
122
exercise_attempts.user, exercise_attempts.worksheet_exercise,
123
as_of=date, allow_inactive=HISTORY_ALLOW_INACTIVE)
125
@reverse_route(ExerciseAttempt)
126
def exerciseattempt_url(exerciseattempt):
127
return (ExerciseAttempts(exerciseattempt.worksheet_exercise,
128
exerciseattempt.user),
129
exerciseattempt.date.strftime(TIMESTAMP_FORMAT)