def mark_q(qid, answers): """ Mark the question according to the answers given in a dictionary and return the result in a dictionary: input: {"A1":"0.345", "A2":"fred", "A3":"-26" } return: {"M1": Mark One, "C1": Comment One, "M2": Mark Two..... } """ qtid = DB.get_q_parent(qid) version = DB.get_q_version(qid) variation = DB.get_q_variation(qid) qvars = DB.get_qt_variation(qtid, variation, version) if not qvars: qvars = {} L.warn("markQuestion(%s, %s) unable to retrieve variables." % (qid, answers)) qvars['OaQID'] = int(qid) marktype = DB.get_qt_marker(qtid) if marktype == 1: # standard marks = mark_q_standard(qvars, answers) else: # We want the latest version of the marker, so no version given markerscript = DB.get_qt_att(qtid, "__marker.py") if not markerscript: markerscript = DB.get_qt_att(qtid, "marker.py") L.info("'marker.py' should now be called '__marker.py' (qtid=%s)" % qtid) if not markerscript: L.info("Unable to retrieve marker script for smart marker question (qtid=%s)!" % qtid) marks = mark_q_standard(qvars, answers) else: marks = mark_q_script(qvars, markerscript, answers) return marks
def get_q_att_fname(qid, name): """ Return (mimetype, filename) with the relevant filename. If it's not found in question, look in questiontemplate. """ qtid = DB.get_q_parent(qid) variation = DB.get_q_variation(qid) version = DB.get_q_version(qid) # for the two biggies we hit the question first, # otherwise check the question template first if name == "image.gif" or name == "qtemplate.html": fname = DB.get_q_att_fname(qtid, name, variation, version) if fname: return DB.get_q_att_mimetype(qtid, name, variation, version), fname fname = DB.get_qt_att_fname(qtid, name, version) if fname: return DB.get_qt_att_mimetype(qtid, name, version), fname else: fname = DB.get_qt_att_fname(qtid, name, version) if fname: return DB.get_qt_att_mimetype(qtid, name, version), fname fname = DB.get_q_att_fname(qtid, name, variation, version) if fname: return DB.get_q_att_mimetype(qtid, name, variation, version), fname return None, None
def render_q_html(q_id, readonly=False): """ Fetch the question html and get it ready for display - replacing links with appropriate targets and filling in form details.""" try: q_id = int(q_id) assert q_id > 0 except (ValueError, TypeError, AssertionError): log(WARN, "renderQuestionHTML(%s,%s) called with bad qid?" % (q_id, readonly)) qt_id = DB.get_q_parent(q_id) try: qt_id = int(qt_id) assert qt_id > 0 except (ValueError, TypeError, AssertionError): log(WARN, "renderQuestionHTML(%s,%s), getparent failed? " % (q_id, readonly)) variation = DB.get_q_variation(q_id) version = DB.get_q_version(q_id) data = DB.get_q_att(qt_id, "qtemplate.html", variation, version) if not data: log(WARN, "Unable to retrieve qtemplate for q_id: %s" % q_id) return "QuestionError" try: out = unicode(data, "utf-8") except UnicodeDecodeError: try: out = unicode(DB.get_q_att(qt_id, "qtemplate.html", variation, version), "latin-1") except UnicodeDecodeError, err: log(ERROR, "unicode error decoding qtemplate for q_id %s: %s" % (q_id, err)) raise
def mark_q(qid, answers): """ Mark the question according to the answers given in a dictionary and return the result in a dictionary: input: {"A1":"0.345", "A2":"fred", "A3":"-26" } return: {"M1": Mark One, "C1": Comment One, "M2": Mark Two..... } """ qtid = DB.get_q_parent(qid) version = DB.get_q_version(qid) variation = DB.get_q_variation(qid) qvars = DB.get_qt_variation(qtid, variation, version) if not qvars: qvars = {} L.warn("markQuestion(%s, %s) unable to retrieve variables." % (qid, answers)) qvars['OaQID'] = int(qid) marktype = DB.get_qt_marker(qtid) if marktype == 1: # standard marks = mark_q_standard(qvars, answers) else: # We want the latest version of the marker, so no version given markerscript = DB.get_qt_att(qtid, "__marker.py") if not markerscript: markerscript = DB.get_qt_att(qtid, "marker.py") L.info("'marker.py' should now be called '__marker.py' (qtid=%s)" % qtid) if not markerscript: L.info( "Unable to retrieve marker script for smart marker question (qtid=%s)!" % qtid) marks = mark_q_standard(qvars, answers) else: marks = mark_q_script(qvars, markerscript, answers) return marks
def practice_mark_question(topic_id, question_id): """ Mark the submitted question answersjust wa """ user_id = session['user_id'] course_id = Topics.get_course_id(topic_id) if not course_id: abort(404) course = Courses2.get_course(course_id) if not course: abort(404) topictitle = "UNKNOWN" try: topictitle = Topics.get_name(topic_id) except KeyError: abort(404) qt_id = DB.get_q_parent(question_id) q_title = DB.get_qt_name(qt_id) questions = Practice.get_sorted_questions(course_id, topic_id, user_id) q_pos = DB.get_qtemplate_topic_pos(qt_id, topic_id) blocked = Practice.is_q_blocked(user_id, course_id, topic_id, qt_id) if blocked: return render_template( "practicequestionblocked.html", mesg=blocked, topictitle=topictitle, topic_id=topic_id, qt_id=qt_id, course=course, q_title=q_title, questions=questions, q_pos=q_pos, ) marking = Practice.mark_q(user_id, topic_id, question_id, request) prev_id, next_id = Practice.get_next_prev(qt_id, topic_id) return render_template( "practicemarkquestion.html", topictitle=topictitle, topic_id=topic_id, qt_id=qt_id, course=course, q_title=q_title, questions=questions, q_pos=q_pos, q_id=question_id, marking=marking, next_id=next_id, prev_id=prev_id )
def practice_mark_question(topic_id, question_id): """ Mark the submitted question answersjust wa """ user_id = session['user_id'] course_id = Topics.get_course_id(topic_id) if not course_id: abort(404) course = Courses2.get_course(course_id) if not course: abort(404) topictitle = "UNKNOWN" try: topictitle = Topics.get_name(topic_id) except KeyError: abort(404) qt_id = DB.get_q_parent(question_id) q_title = DB.get_qt_name(qt_id) questions = Practice.get_sorted_questions(course_id, topic_id, user_id) q_pos = DB.get_qtemplate_topic_pos(qt_id, topic_id) blocked = Practice.is_q_blocked(user_id, course_id, topic_id, qt_id) if blocked: return render_template( "practicequestionblocked.html", mesg=blocked, topictitle=topictitle, topic_id=topic_id, qt_id=qt_id, course=course, q_title=q_title, questions=questions, q_pos=q_pos, ) marking = Practice.mark_q(user_id, topic_id, question_id, request) prev_id, next_id = Practice.get_next_prev(qt_id, topic_id) # TODO: need next_pos and prev_pos return render_template( "practicemarkquestion.html", topictitle=topictitle, topic_id=topic_id, qt_id=qt_id, course=course, q_title=q_title, questions=questions, q_pos=q_pos, q_id=question_id, marking=marking, next_id=next_id, prev_id=prev_id )
def render_mark_results(qid, marks): """Take the marking results and display something for the student that tells them what they got right and wrong. If the question has an attachment "_rendermarks.py", it will be called, otherwise a default HTML table will be returned. _rendermarks.py should set variable "resultsHTML" to contain a suitable string for putting in an HTML page. """ qtid = DB.get_q_parent(qid) renderscript = DB.get_qt_att(qtid, "__results.py") if not renderscript: resultshtml = render_mark_results_standard(qid, marks) else: resultshtml = render_mark_results_script(qtid, qid, marks, renderscript) return resultshtml
def get_q_att(qid, name): """ Return (mimetype, data) with the relevant attachment. If it's not found in question, look in questiontemplate. """ qtid = DB.get_q_parent(qid) variation = DB.get_q_variation(qid) version = DB.get_q_version(qid) # for the two biggies we hit the question first, # otherwise check the question template first if name == "image.gif" or name == "qtemplate.html": data = DB.get_q_att(qtid, name, variation, version) if data: return DB.get_q_att_mimetype(qtid, name, variation, version), data data = DB.get_qt_att(qtid, name, version) if data: return DB.get_qt_att_mimetype(qtid, name, version), data else: data = DB.get_qt_att(qtid, name, version) if data: return DB.get_qt_att_mimetype(qtid, name, version), data data = DB.get_q_att(qtid, name, variation, version) if data: return DB.get_q_att_mimetype(qtid, name, variation, version), data return None, None
def render_q_html(q_id, readonly=False): """ Fetch the question html and get it ready for display - replacing links with appropriate targets and filling in form details.""" try: q_id = int(q_id) assert q_id > 0 except (ValueError, TypeError, AssertionError): L.warn("renderQuestionHTML(%s,%s) called with bad qid?" % (q_id, readonly)) qt_id = DB.get_q_parent(q_id) try: qt_id = int(qt_id) assert qt_id > 0 except (ValueError, TypeError, AssertionError): L.warn("renderQuestionHTML(%s,%s), getparent failed? " % (q_id, readonly)) variation = DB.get_q_variation(q_id) version = DB.get_q_version(q_id) data = DB.get_q_att(qt_id, "qtemplate.html", variation, version) if not data: L.warn("Unable to retrieve qtemplate for q_id: %s" % q_id) return "QuestionError" try: out = unicode(data, "utf-8") except UnicodeDecodeError: try: out = unicode(DB.get_q_att(qt_id, "qtemplate.html", variation, version), "latin-1") except UnicodeDecodeError as err: L.error("unicode error decoding qtemplate for q_id %s: %s" % (q_id, err)) raise out = out.replace("This question is not verified yet, please report any error!", "") out = out.replace("ANS_", "Q_%d_ANS_" % (q_id,)) out = out.replace("$IMAGES$", "%s/att/qatt/%s/%s/%s/" % (OaConfig.parentURL, qt_id, version, variation)) out = out.replace("$APPLET$", "%s/att/qatt/%s/%s/%s/" % (OaConfig.parentURL, qt_id, version, variation)) out = out.replace("$STATIC$", "%s/att/qtatt/%s/%s/%s/" % (OaConfig.parentURL, qt_id, version, variation)) if readonly: out = out.replace("<INPUT ", "<INPUT READONLY ") out = out.replace("<SELECT ", "<SELECT DISABLED=DISABLED STYLE='color: black;'") guesses = DB.get_q_guesses(q_id) for guess in guesses.keys(): # noinspection PyComparisonWithNone if guesses[guess] == None: # If it's 0 we want to leave it alone guesses[guess] = "" if guesses[guess] == "None": guesses[guess] = "" # for each question if guesses: for ques in range(25, 0, -1): if ("G%d" % ques) in guesses: out = out.replace("VAL_%d" % ques, htmlesc(guesses["G%d" % ques])) for part in range(50, 0, -1): if guesses["G%d" % ques] == "%s.0" % part or guesses["G%d" % ques] == "%s" % part: out = out.replace("Oa_SEL_%d_%d" % (ques, part), "SELECTED") out = out.replace("Oa_CHK_%d_%d" % (ques, part), "CHECKED") else: out = out.replace("Oa_SEL_%d_%d" % (ques, part), "") out = out.replace("Oa_CHK_%d_%d" % (ques, part), "") else: out = out.replace("VAL_%d" % (ques,), "") for ques in range(25, 0, -1): out = out.replace("VAL_%d" % (ques,), "") return out
def render_own_marked_exam(student, exam): """ Return a students instance of the exam, with HTML version of the question, their answers, and a marking summary. returns list of questions/marks [ {'pos': position, 'html': rendered (marked) question, 'marking': [ 'part': part number, 'guess': student guess, 'correct': correct answer, 'mark': (float) mark, 'tolerance': marking tolerance, 'comment': marking comment ] }, ... ] """ questions = General.get_exam_qs(student, exam) firstview, examsubmit = student_exam_duration(student, exam) results = [] if not examsubmit: return [{'pos': 1, 'html': "In Progress", 'marking': {} }, ], False examtotal = 0.0 for question in questions: qtemplate = DB.get_q_parent(question) answers = DB.get_q_guesses_before_time(question, examsubmit) pos = DB.get_qt_exam_pos(exam, qtemplate) marks = General.mark_q(question, answers) parts = [int(var[1:]) for var in marks.keys() if re.search("^A([0-9]+$)", var) > 0] parts.sort() marking = [] for part in parts: guess = marks['G%d' % (part,)] if guess == "None": guess = None answer = marks['A%d' % (part,)] score = marks['M%d' % (part,)] tolerance = marks['T%d' % (part,)] comment = marks['C%d' % (part,)] examtotal += score marking.append({ 'part': part, 'guess': guess, 'correct': answer, 'mark': score, 'tolerance': tolerance, 'comment': comment }) html = General.render_q_html(question) results.append({ 'pos': pos, 'html': html, 'marking': marking }) return results, examtotal
def render_q_html(q_id, readonly=False): """ Fetch the question html and get it ready for display - replacing links with appropriate targets and filling in form details.""" try: q_id = int(q_id) assert q_id > 0 except (ValueError, TypeError, AssertionError): L.warn("renderQuestionHTML(%s,%s) called with bad qid?" % (q_id, readonly)) qt_id = DB.get_q_parent(q_id) try: qt_id = int(qt_id) assert qt_id > 0 except (ValueError, TypeError, AssertionError): L.warn("renderQuestionHTML(%s,%s), getparent failed? " % (q_id, readonly)) variation = DB.get_q_variation(q_id) version = DB.get_q_version(q_id) data = DB.get_q_att(qt_id, "qtemplate.html", variation, version) if not data: L.warn("Unable to retrieve qtemplate for q_id: %s" % q_id) return "QuestionError" try: out = unicode(data, "utf-8") except UnicodeDecodeError: try: out = unicode( DB.get_q_att(qt_id, "qtemplate.html", variation, version), "latin-1") except UnicodeDecodeError as err: L.error("unicode error decoding qtemplate for q_id %s: %s" % (q_id, err)) raise out = out.replace( "This question is not verified yet, please report any error!", "") out = out.replace("ANS_", "Q_%d_ANS_" % (q_id, )) out = out.replace( "$IMAGES$", "%s/att/qatt/%s/%s/%s/" % (OaConfig.parentURL, qt_id, version, variation)) out = out.replace( "$APPLET$", "%s/att/qatt/%s/%s/%s/" % (OaConfig.parentURL, qt_id, version, variation)) out = out.replace( "$STATIC$", "%s/att/qtatt/%s/%s/%s/" % (OaConfig.parentURL, qt_id, version, variation)) if readonly: out = out.replace("<INPUT ", "<INPUT READONLY ") out = out.replace("<SELECT ", "<SELECT DISABLED=DISABLED STYLE='color: black;'") guesses = DB.get_q_guesses(q_id) for guess in guesses.keys(): # noinspection PyComparisonWithNone if guesses[guess] == None: # If it's 0 we want to leave it alone guesses[guess] = "" if guesses[guess] == "None": guesses[guess] = "" # for each question if guesses: for ques in range(25, 0, -1): if ("G%d" % ques) in guesses: out = out.replace("VAL_%d" % ques, htmlesc(guesses["G%d" % ques])) for part in range(50, 0, -1): if guesses["G%d" % ques] == "%s.0" % part or guesses[ "G%d" % ques] == "%s" % part: out = out.replace("Oa_SEL_%d_%d" % (ques, part), "SELECTED") out = out.replace("Oa_CHK_%d_%d" % (ques, part), "CHECKED") else: out = out.replace("Oa_SEL_%d_%d" % (ques, part), "") out = out.replace("Oa_CHK_%d_%d" % (ques, part), "") else: out = out.replace("VAL_%d" % (ques, ), "") for ques in range(25, 0, -1): out = out.replace("VAL_%d" % (ques, ), "") return out
def render_own_marked_exam(student, exam): """ Return a students instance of the exam, with HTML version of the question, their answers, and a marking summary. returns list of questions/marks [ {'pos': position, 'html': rendered (marked) question, 'marking': [ 'part': part number, 'guess': student guess, 'correct': correct answer, 'mark': (float) mark, 'tolerance': marking tolerance, 'comment': marking comment ] }, ... ] """ questions = General.get_exam_qs(student, exam) firstview, examsubmit = student_exam_duration(student, exam) results = [] if not examsubmit: return [ { 'pos': 1, 'html': "In Progress", 'marking': {} }, ], False examtotal = 0.0 for question in questions: qtemplate = DB.get_q_parent(question) answers = DB.get_q_guesses_before_time(question, examsubmit) pos = DB.get_qt_exam_pos(exam, qtemplate) marks = General.mark_q(question, answers) parts = [ int(var[1:]) for var in marks.keys() if re.search("^A([0-9]+$)", var) > 0 ] parts.sort() marking = [] for part in parts: guess = marks['G%d' % (part, )] if guess == "None": guess = None answer = marks['A%d' % (part, )] score = marks['M%d' % (part, )] tolerance = marks['T%d' % (part, )] comment = marks['C%d' % (part, )] examtotal += score marking.append({ 'part': part, 'guess': guess, 'correct': answer, 'mark': score, 'tolerance': tolerance, 'comment': comment }) html = General.render_q_html(question) results.append({'pos': pos, 'html': html, 'marking': marking}) return results, examtotal