39
39
import ivle.database
40
40
from ivle.database import Subject, Offering, Semester, Exercise, \
41
41
ExerciseSave, WorksheetExercise, ExerciseAttempt
42
from ivle.database import Worksheet as DBWorksheet
42
from ivle.database import Worksheet
43
43
import ivle.worksheet.utils
44
44
from ivle.webapp import ApplicationRoot
45
45
from ivle.webapp.base.views import BaseView
64
64
from ivle.webapp.tutorial.media import (SubjectMediaFile, SubjectMediaView,
68
"""This class represents a worksheet and a particular students progress
71
Do not confuse this with a worksheet in the database. This worksheet
72
has extra information for use in the output, such as marks."""
73
def __init__(self, id, name, assessable):
76
self.assessable = assessable
77
self.complete_class = ''
78
self.optional_message = ''
82
return ("Worksheet(id=%s, name=%s, assessable=%s)"
83
% (repr(self.id), repr(self.name), repr(self.assessable)))
85
class OfferingView(XHTMLView):
86
'''The view of the index of worksheets for an offering.'''
87
template = 'templates/subjectmenu.html'
88
tab = 'subjects' # XXX
90
breadcrumb_text = 'Worksheets'
92
def populate(self, req, ctx):
93
"""Create the context for the given offering."""
94
self.plugin_styles[Plugin] = ['tutorial.css']
96
ctx['subject'] = self.context.subject
97
ctx['offering'] = self.context
98
ctx['user'] = req.user
100
# As we go, calculate the total score for this subject
101
# (Assessable worksheets only, mandatory problems only)
103
ctx['worksheets'] = []
106
# Offering.worksheets is ordered by the worksheets seq_no
107
for worksheet in self.context.worksheets:
108
new_worksheet = Worksheet(worksheet.identifier, worksheet.name,
109
worksheet.assessable)
110
if new_worksheet.assessable:
111
# Calculate the user's score for this worksheet
112
mand_done, mand_total, opt_done, opt_total = (
113
ivle.worksheet.utils.calculate_score(req.store, req.user,
116
optional_message = " (excluding optional exercises)"
118
optional_message = ""
119
if mand_done >= mand_total:
120
new_worksheet.complete_class = "complete"
122
new_worksheet.complete_class = "semicomplete"
124
new_worksheet.complete_class = "incomplete"
125
problems_done += mand_done
126
problems_total += mand_total
127
new_worksheet.mand_done = mand_done
128
new_worksheet.total = mand_total
129
new_worksheet.optional_message = optional_message
130
ctx['worksheets'].append(new_worksheet)
132
ctx['problems_total'] = problems_total
133
ctx['problems_done'] = problems_done
134
if problems_total > 0:
135
if problems_done >= problems_total:
136
ctx['complete_class'] = "complete"
137
elif problems_done > 0:
138
ctx['complete_class'] = "semicomplete"
140
ctx['complete_class'] = "incomplete"
141
# Calculate the final percentage and mark for the subject
142
ctx['problems_pct'], ctx['mark'], ctx['max_mark'] = (
143
ivle.worksheet.utils.calculate_mark(
144
problems_done, problems_total))
146
68
class WorksheetView(XHTMLView):
147
69
'''The view of a worksheet with exercises.'''
382
304
def _to_python(self, value, state):
383
305
if (state.store.find(
384
DBWorksheet, offering=state.offering,
306
Worksheet, offering=state.offering,
385
307
identifier=value).one() not in (None, state.existing_worksheet)):
386
308
raise formencode.Invalid(
387
309
'Short name already taken', value, state)
642
564
exerciseattempts_url, exerciseattempt_url)
644
566
breadcrumbs = {Exercise: ExerciseBreadcrumb,
645
DBWorksheet: WorksheetBreadcrumb
567
Worksheet: WorksheetBreadcrumb
648
views = [(Offering, ('+worksheets', '+index'), OfferingView),
649
(Offering, ('+worksheets', '+new'), WorksheetAddView),
570
views = [(Offering, ('+worksheets', '+new'), WorksheetAddView),
650
571
(Offering, ('+worksheets', '+edit'), WorksheetsEditView),
651
(DBWorksheet, '+index', WorksheetView),
652
(DBWorksheet, '+edit', WorksheetEditView),
572
(Worksheet, '+index', WorksheetView),
573
(Worksheet, '+edit', WorksheetEditView),
653
574
(ApplicationRoot, ('+exercises', '+index'), ExercisesView),
654
575
(ApplicationRoot, ('+exercises', '+add'), ExerciseAddView),
655
576
(Exercise, '+index', ExerciseView),