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

294 by mattgiuca
Added application: tutorialservice. Will be used as the Ajax backend for
1
# IVLE - Informatics Virtual Learning Environment
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
2
# Copyright (C) 2007-2009 The University of Melbourne
294 by mattgiuca
Added application: tutorialservice. Will be used as the Ajax backend for
3
#
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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
18
# Author: Matt Giuca, Nick Chadwick
19
20
'''AJAX backend for the tutorial application.'''
300 by mattgiuca
conf/apps: Added TutorialService as a registered app.
21
1080.1.58 by Matt Giuca
ivle.worksheet: Added get_exercise_attempts and get_exercise_attempt.
22
import datetime
1294.2.64 by William Grant
Port tutorial stuff.
23
1099.4.3 by Nick Chadwick
Updated the tutorial service, to now allow users to edit worksheets
24
import genshi
1294.2.64 by William Grant
Port tutorial stuff.
25
from storm.locals import Store
301 by mattgiuca
tutorialservice: Now parses and executes the students code using the test
26
1080.1.58 by Matt Giuca
ivle.worksheet: Added get_exercise_attempts and get_exercise_attempt.
27
import ivle.database
1099.4.3 by Nick Chadwick
Updated the tutorial service, to now allow users to edit worksheets
28
from ivle.database import Exercise, ExerciseAttempt, ExerciseSave, Worksheet, \
1294.2.64 by William Grant
Port tutorial stuff.
29
                          Offering, Subject, Semester, User, WorksheetExercise
1099.1.220 by Nick Chadwick
Merged from trunk
30
import ivle.worksheet.utils
1099.1.113 by William Grant
Give console and tutorial services security declarations.
31
from ivle.webapp.base.rest import (JSONRESTView, named_operation,
32
                                   require_permission)
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
33
from ivle.webapp.errors import NotFound
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
34
1025 by mattgiuca
tutorialservice: Added two new GET actions: getattempts and getattempt.
35
1080.1.88 by William Grant
ivle.worksheet: Add a save_exercise function.
36
TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S'
37
1394.2.8 by William Grant
Factor out console-based exercise testing into ivle.worksheet.test_exercise_submission().
38
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
39
class AttemptsRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
40
    '''REST view of a user's attempts at an exercise.'''
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
41
1099.1.113 by William Grant
Give console and tutorial services security declarations.
42
    @require_permission('edit')
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
43
    def GET(self, req):
44
        """Handles a GET Attempts action."""
1099.1.141 by Nick Chadwick
Updated the exercises to be loaded from the database, not a local file.
45
        attempts = req.store.find(ExerciseAttempt, 
1294.2.64 by William Grant
Port tutorial stuff.
46
                ExerciseAttempt.ws_ex_id == self.context.worksheet_exercise.id,
47
                ExerciseAttempt.user_id == self.context.user.id)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
48
        # attempts is a list of ExerciseAttempt objects. Convert to dictionaries
49
        time_fmt = lambda dt: datetime.datetime.strftime(dt, TIMESTAMP_FORMAT)
50
        attempts = [{'date': time_fmt(a.date), 'complete': a.complete}
1080.1.58 by Matt Giuca
ivle.worksheet: Added get_exercise_attempts and get_exercise_attempt.
51
                for a in attempts]
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
52
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
53
        return attempts
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
54
55
1099.1.113 by William Grant
Give console and tutorial services security declarations.
56
    @require_permission('edit')
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
57
    def PUT(self, req, data):
1099.1.114 by Nick Chadwick
Modified the database so that exercises are now stored in the database, rather
58
        """ Tests the given submission """
1394.2.8 by William Grant
Factor out console-based exercise testing into ivle.worksheet.test_exercise_submission().
59
        test_results = ivle.worksheet.utils.test_exercise_submission(
60
            req.config, req.user, self.context.worksheet_exercise.exercise,
61
            data['code'])
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
62
63
        attempt = ivle.database.ExerciseAttempt(user=req.user,
1294.2.64 by William Grant
Port tutorial stuff.
64
            worksheet_exercise = self.context.worksheet_exercise,
1099.1.180 by Nick Chadwick
This commit changes the tutorial service, which now almost exclusively
65
            date = datetime.datetime.now(),
66
            complete = test_results['passed'],
67
            text = unicode(data['code'])
68
        )
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
69
70
        req.store.add(attempt)
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
71
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
72
        # Query the DB to get an updated score on whether or not this problem
73
        # has EVER been completed (may be different from "passed", if it has
74
        # been completed before), and the total number of attempts.
1099.1.220 by Nick Chadwick
Merged from trunk
75
        completed, attempts = ivle.worksheet.utils.get_exercise_status(
1294.2.64 by William Grant
Port tutorial stuff.
76
                req.store, req.user, self.context.worksheet_exercise)
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
77
        test_results["completed"] = completed
78
        test_results["attempts"] = attempts
79
80
        return test_results
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
81
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
82
83
class AttemptRESTView(JSONRESTView):
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
84
    '''REST view of an exercise attempt.'''
85
1099.1.113 by William Grant
Give console and tutorial services security declarations.
86
    @require_permission('view')
1099.1.87 by William Grant
Fix views in ivle.webapp.admin and ivle.webapp.tutorial to return 404 wherever
87
    def GET(self, req):
88
        return {'code': self.context.text}
1099.1.70 by William Grant
Clean up ivle.webapp.tutorial.service.
89
90
1099.1.216 by Nick Chadwick
Started adding in add and save options in the exercise edit view, to
91
class WorksheetExerciseRESTView(JSONRESTView):
1131 by William Grant
Offerings now give 'view' only to user enrolled in them. 'edit' is granted
92
    '''REST view of a worksheet exercise.'''
93
94
    @named_operation('view')
1099.1.58 by Nick Chadwick
Updated the Worksheets to use a new tutorialservice, hosted in the
95
    def save(self, req, text):
1099.1.180 by Nick Chadwick
This commit changes the tutorial service, which now almost exclusively
96
        # Find the appropriate WorksheetExercise to save to. If its not found,
97
        # the user is submitting against a non-existant worksheet/exercise
98
1099.1.182 by Nick Chadwick
Added a view to allow admins to edit worksheets
99
        old_save = req.store.find(ExerciseSave,
1131 by William Grant
Offerings now give 'view' only to user enrolled in them. 'edit' is granted
100
            ExerciseSave.ws_ex_id == self.context.id,
1099.1.182 by Nick Chadwick
Added a view to allow admins to edit worksheets
101
            ExerciseSave.user == req.user).one()
102
        
103
        #Overwrite the old, or create a new if there isn't one
104
        if old_save is None:
105
            new_save = ExerciseSave()
106
            req.store.add(new_save)
107
        else:
108
            new_save = old_save
109
        
1131 by William Grant
Offerings now give 'view' only to user enrolled in them. 'edit' is granted
110
        new_save.worksheet_exercise = self.context
1099.1.180 by Nick Chadwick
This commit changes the tutorial service, which now almost exclusively
111
        new_save.user = req.user
112
        new_save.text = unicode(text)
113
        new_save.date = datetime.datetime.now()
1099.1.182 by Nick Chadwick
Added a view to allow admins to edit worksheets
114
1099.1.49 by Nick Chadwick
Began moving tutorialservice over to webapp.
115
        return {"result": "ok"}
1099.4.1 by Nick Chadwick
Working on putting worksheets into the database.
116
1099.1.180 by Nick Chadwick
This commit changes the tutorial service, which now almost exclusively
117
1099.1.189 by Nick Chadwick
Updated service.py to correctly add a seq_no to a worksheet before
118
class WorksheetsRESTView(JSONRESTView):
119
    """View used to update and create Worksheets."""
1099.1.182 by Nick Chadwick
Added a view to allow admins to edit worksheets
120
1542 by Matt Giuca
Tutors can now (once again) edit worksheets.
121
    @named_operation('edit_worksheets')
1099.1.197 by Nick Chadwick
Modified worksheets edit view, so now there are links to edit, add,
122
    def move_up(self, req, worksheetid):
123
        """Takes a list of worksheet-seq_no pairs and updates their 
124
        corresponding Worksheet objects to match."""
125
        
126
        worksheet_below = req.store.find(Worksheet,
127
            Worksheet.offering_id == self.context.id,
128
            Worksheet.identifier == unicode(worksheetid)).one()
129
        if worksheet_below is None:
130
            raise NotFound('worksheet_below')
131
        worksheet_above = req.store.find(Worksheet,
132
            Worksheet.offering_id == self.context.id,
133
            Worksheet.seq_no == (worksheet_below.seq_no - 1)).one()
134
        if worksheet_above is None:
135
            raise NotFound('worksheet_above')
136
137
        worksheet_below.seq_no = worksheet_below.seq_no - 1
138
        worksheet_above.seq_no = worksheet_above.seq_no + 1
139
        
140
        return {'result': 'ok'}
141
1542 by Matt Giuca
Tutors can now (once again) edit worksheets.
142
    @named_operation('edit_worksheets')
1099.1.197 by Nick Chadwick
Modified worksheets edit view, so now there are links to edit, add,
143
    def move_down(self, req, worksheetid):
144
        """Takes a list of worksheet-seq_no pairs and updates their 
145
        corresponding Worksheet objects to match."""
146
        
147
        worksheet_above = req.store.find(Worksheet,
148
            Worksheet.offering_id == self.context.id,
149
            Worksheet.identifier == unicode(worksheetid)).one()
150
        if worksheet_above is None:
151
            raise NotFound('worksheet_below')
152
        worksheet_below = req.store.find(Worksheet,
153
            Worksheet.offering_id == self.context.id,
154
            Worksheet.seq_no == (worksheet_above.seq_no + 1)).one()
155
        if worksheet_below is None:
156
            raise NotFound('worksheet_above')
157
158
        worksheet_below.seq_no = worksheet_below.seq_no - 1
159
        worksheet_above.seq_no = worksheet_above.seq_no + 1
1099.1.189 by Nick Chadwick
Updated service.py to correctly add a seq_no to a worksheet before
160
        
161
        return {'result': 'ok'}