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

« back to all changes in this revision

Viewing changes to www/apps/tutorial/__init__.py

  • Committer: stevenbird
  • Date: 2008-02-19 23:12:46 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:515
Propagated "problem" -> "exercise" nomenclature change.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
# Date: 25/1/2008
21
21
 
22
22
# Tutorial application.
23
 
# Displays tutorial content with editable problems, allowing students to test
24
 
# and submit their solutions to problems and have them auto-tested.
 
23
# Displays tutorial content with editable exercises, allowing students to test
 
24
# and submit their solutions to exercises and have them auto-tested.
25
25
 
26
26
# URL syntax
27
27
# All path segments are optional (omitted path segments will show menus).
201
201
        % (cgi.escape(subject), cgi.escape(worksheetname)))
202
202
 
203
203
    # Write each element
204
 
    problemid = 0
 
204
    exerciseid = 0
205
205
    for node in worksheetdom.childNodes:
206
 
        problemid = present_worksheet_node(req, node, problemid)
 
206
        exerciseid = present_worksheet_node(req, node, exerciseid)
207
207
    req.write("</div>\n")   # tutorialbody
208
208
 
209
 
def present_worksheet_node(req, node, problemid):
 
209
def present_worksheet_node(req, node, exerciseid):
210
210
    """Given a node of a worksheet XML document, writes it out to the
211
 
    request. This recursively searches for "problem" elements and handles
212
 
    those specially (presenting their XML problem spec and input box), and
 
211
    request. This recursively searches for "exercise" elements and handles
 
212
    those specially (presenting their XML exercise spec and input box), and
213
213
    just dumps the other elements as regular HTML.
214
214
 
215
 
    problemid is the ID to use for the first problem.
216
 
    Returns the new problemid after all the problems have been written
217
 
    (since we need unique IDs for each problem).
 
215
    exerciseid is the ID to use for the first exercise.
 
216
    Returns the new exerciseid after all the exercises have been written
 
217
    (since we need unique IDs for each exercise).
218
218
    """
219
219
    if node.nodeType == node.ELEMENT_NODE:
220
 
        if node.tagName == "problem":
221
 
            present_problem(req, node.getAttribute("src"), problemid)
222
 
            problemid += 1
 
220
        if node.tagName == "exercise":
 
221
            present_exercise(req, node.getAttribute("src"), exerciseid)
 
222
            exerciseid += 1
223
223
        else:
224
224
            # Some other element. Write out its head and foot, and recurse.
225
225
            req.write("<" + node.tagName)
230
230
                req.write(" " + ' '.join(attrs))
231
231
            req.write(">")
232
232
            for childnode in node.childNodes:
233
 
                problemid = present_worksheet_node(req, childnode, problemid)
 
233
                exerciseid = present_worksheet_node(req, childnode, exerciseid)
234
234
            req.write("</" + node.tagName + ">")
235
235
    else:
236
236
        # No need to recurse, so just print this node's contents
237
237
        req.write(node.toxml())
238
 
    return problemid
 
238
    return exerciseid
239
239
 
240
240
def innerXML(elem):
241
241
    """Given an element, returns its children as XML strings concatenated
258
258
 
259
259
    return data.strip()
260
260
 
261
 
def present_problem(req, problemsrc, problemid):
262
 
    """Open a problem file, and write out the problem to the request in HTML.
263
 
    problemsrc: "src" of the problem file. A path relative to the top-level
264
 
        problems base directory, as configured in conf.
 
261
def present_exercise(req, exercisesrc, exerciseid):
 
262
    """Open a exercise file, and write out the exercise to the request in HTML.
 
263
    exercisesrc: "src" of the exercise file. A path relative to the top-level
 
264
        exercises base directory, as configured in conf.
265
265
    """
266
 
    req.write('<div class="tuteproblem" id="problem%d">\n'
267
 
        % problemid)
 
266
    req.write('<div class="exercise" id="exercise%d">\n'
 
267
        % exerciseid)
268
268
    # First normalise the path
269
 
    problemsrc = os.path.normpath(problemsrc)
 
269
    exercisesrc = os.path.normpath(exercisesrc)
270
270
    # Now if it begins with ".." or separator, then it's illegal
271
 
    if problemsrc.startswith("..") or problemsrc.startswith(os.sep):
272
 
        problemfile = None
 
271
    if exercisesrc.startswith("..") or exercisesrc.startswith(os.sep):
 
272
        exercisefile = None
273
273
    else:
274
 
        problemfile = os.path.join(conf.problems_base, problemsrc)
 
274
        exercisefile = os.path.join(conf.exercises_base, exercisesrc)
275
275
 
276
276
    try:
277
 
        problemfile = open(problemfile)
278
 
    except (TypeError, IOError):    # TypeError if problemfile == None
 
277
        exercisefile = open(exercisefile)
 
278
    except (TypeError, IOError):    # TypeError if exercisefile == None
279
279
        req.write("<p><b>Server Error</b>: "
280
 
            + "Problem file could not be opened.</p>\n")
 
280
            + "Exercise file could not be opened.</p>\n")
281
281
        req.write("</div>\n")
282
282
        return
283
283
    
284
 
    # Read problem file and present the problem
 
284
    # Read exercise file and present the exercise
285
285
    # Note: We do not use the testing framework because it does a lot more
286
 
    # work than we need. We just need to get the problem name and a few other
 
286
    # work than we need. We just need to get the exercise name and a few other
287
287
    # fields from the XML.
288
288
 
289
 
    problemdom = minidom.parse(problemfile)
290
 
    problemfile.close()
291
 
    problemdom = problemdom.documentElement
292
 
    if problemdom.tagName != "problem":
 
289
    exercisedom = minidom.parse(exercisefile)
 
290
    exercisefile.close()
 
291
    exercisedom = exercisedom.documentElement
 
292
    if exercisedom.tagName != "exercise":
293
293
        # TODO: Nicer error message, to help authors
294
294
        req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR)
295
 
    problemname = problemdom.getAttribute("name")
296
 
    rows = problemdom.getAttribute("rows")
 
295
    exercisename = exercisedom.getAttribute("name")
 
296
    rows = exercisedom.getAttribute("rows")
297
297
    if not rows:
298
298
        rows = "12"
299
299
    # Look for some other fields we need, which are elements:
300
300
    # - desc
301
301
    # - partial
302
 
    problemdesc = None
303
 
    problempartial= ""
304
 
    for elem in problemdom.childNodes:
 
302
    exercisedesc = None
 
303
    exercisepartial= ""
 
304
    for elem in exercisedom.childNodes:
305
305
        if elem.nodeType == elem.ELEMENT_NODE:
306
306
            if elem.tagName == "desc":
307
 
                problemdesc = innerXML(elem).strip()
 
307
                exercisedesc = innerXML(elem).strip()
308
308
            if elem.tagName == "partial":
309
 
                problempartial= getTextData(elem) + '\n'
 
309
                exercisepartial= getTextData(elem) + '\n'
310
310
 
311
 
    # Print this problem out to HTML 
312
 
    req.write("<p><b>Exercise:</b> %s</p>\n" % problemname)
313
 
    if problemdesc is not None:
314
 
        req.write("<div>%s</div>\n" % problemdesc)
315
 
    req.write('<textarea class="problembox" cols="80" rows="%s">%s</textarea>'
316
 
            % (rows, problempartial))
317
 
    filename = cgi.escape(cjson.encode(problemsrc), quote=True)
318
 
    req.write("""\n<div class="problembuttons">
 
311
    # Print this exercise out to HTML 
 
312
    req.write("<p><b>Exercise:</b> %s</p>\n" % exercisename)
 
313
    if exercisedesc is not None:
 
314
        req.write("<div>%s</div>\n" % exercisedesc)
 
315
    req.write('<textarea class="exercisebox" cols="80" rows="%s">%s</textarea>'
 
316
            % (rows, exercisepartial))
 
317
    filename = cgi.escape(cjson.encode(exercisesrc), quote=True)
 
318
    req.write("""\n<div class="exercisebuttons">
319
319
  <input type="button" value="Run"
320
 
    onclick="runproblem(&quot;problem%d&quot;, %s)" />
 
320
    onclick="runexercise(&quot;exercise%d&quot;, %s)" />
321
321
  <input type="button" value="Submit"
322
 
    onclick="submitproblem(&quot;problem%d&quot;, %s)" />
 
322
    onclick="submitexercise(&quot;exercise%d&quot;, %s)" />
323
323
</div>
324
324
<div class="testoutput">
325
325
</div>
326
 
""" % (problemid, filename, problemid, filename))
 
326
""" % (exerciseid, filename, exerciseid, filename))
327
327
    req.write("</div>\n")