コード例 #1
0
ファイル: test_qengine.py プロジェクト: tkanesh/oasisqe
def test_instance_generate_multif_answer():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on multif choice "ANSWER"

        No side effects.
    """

    tmpl = "blah<ANSWER1 MULTIF f,g,h,i>blah"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33}
    html = """blah<table border=0><tr><td>Please choose one:</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='1' Oa_CHK_1_1>7</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='2' Oa_CHK_1_2>joe</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='3' Oa_CHK_1_3>3.4</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='4' Oa_CHK_1_4>33</td></tr></table><br />
blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "blah<ANSWER1 MULTIF f,g,h,i,j>blah"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33, "j": "&amp;"}
    html = """blah<table border=0><tr><td>Please choose one:</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='1' Oa_CHK_1_1>7</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='2' Oa_CHK_1_2>joe</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='3' Oa_CHK_1_3>3.4</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='4' Oa_CHK_1_4>33</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='5' Oa_CHK_1_5>&amp;</td></tr></table><br />
blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "blah<ANSWER1 MULTIF f,g,h,"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33, "j": "&amp;"}
    html = """blah<ANSWER1 MULTIF f,g,h,"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "blah<ANSWER1 MULTIF f,g,h,i,j>"
    qvars = {'f': 7, 'g': "joe"}
    html = """blah<table border=0><tr><td>Please choose one:</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='1' Oa_CHK_1_1>7</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='2' Oa_CHK_1_2>joe</td><FONT COLOR="red">ERROR IN QUESTION DATA</FONT><FONT COLOR="red">ERROR IN QUESTION DATA</FONT><FONT COLOR="red">ERROR IN QUESTION DATA</FONT></tr></table><br />\n"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html
コード例 #2
0
ファイル: test_qengine.py プロジェクト: ehchua/oasisqe
def test_instance_generate_multif_answer():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on multif choice "ANSWER"

        No side effects.
    """

    tmpl = "blah<ANSWER1 MULTIF f,g,h,i>blah"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33}
    html = """blah<table border=0><tr><td>Please choose one:</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='1' Oa_CHK_1_1>7</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='2' Oa_CHK_1_2>joe</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='3' Oa_CHK_1_3>3.4</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='4' Oa_CHK_1_4>33</td></tr></table><br />
blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "blah<ANSWER1 MULTIF f,g,h,i,j>blah"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33, "j": "&amp;"}
    html = """blah<table border=0><tr><td>Please choose one:</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='1' Oa_CHK_1_1>7</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='2' Oa_CHK_1_2>joe</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='3' Oa_CHK_1_3>3.4</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='4' Oa_CHK_1_4>33</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='5' Oa_CHK_1_5>&amp;</td></tr></table><br />
blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "blah<ANSWER1 MULTIF f,g,h,"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33, "j": "&amp;"}
    html = """blah<ANSWER1 MULTIF f,g,h,"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "blah<ANSWER1 MULTIF f,g,h,i,j>"
    qvars = {'f': 7, 'g': "joe"}
    html = """blah<table border=0><tr><td>Please choose one:</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='1' Oa_CHK_1_1>7</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='2' Oa_CHK_1_2>joe</td><FONT COLOR="red">ERROR IN QUESTION DATA</FONT><FONT COLOR="red">ERROR IN QUESTION DATA</FONT><FONT COLOR="red">ERROR IN QUESTION DATA</FONT></tr></table><br />\n"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html
コード例 #3
0
ファイル: Practice.py プロジェクト: ehchua/oasisqe
def mark_q(user_id, topic_id, q_id, request):
    """Mark the question and return the results"""
    answers = {}
    for i in request.form.keys():
        part = re.search(r"^Q_(\d+)_ANS_(\d+)$", i)
        if part:
            newqid = int(part.groups()[0])
            part = int(part.groups()[1])
            if newqid == q_id:
                value = request.form[i]
                answers["G%d" % part] = value
                DB.save_guess(newqid, part, value)
            else:
                L.warn("received guess for wrong question? (%d,%d,%d,%s)" %
                    (user_id, topic_id, q_id, request.form))
    try:
        marks = General.mark_q(q_id, answers)
        DB.set_q_status(q_id, 3)    # 3 = marked
        DB.set_q_marktime(q_id)
    except OaMarkerError:
        L.warn("Marker Error - (%d, %d, %d, %s)" %
            (user_id, topic_id, q_id, request.form))
        marks = {}
    q_body = General.render_mark_results(q_id, marks)
    parts = [int(var[1:])
             for var in marks.keys()
             if re.search(r"^A([0-9]+)$", var) > 0]
    parts.sort()
    total = 0.0
    for part in parts:
        if 'M%d' % (part,) in marks:
            total += float(marks['M%d' % (part,)])
    DB.update_q_score(q_id, total)    # 3 = marked
    DB.set_q_status(q_id, 2)
    return q_body
コード例 #4
0
ファイル: test_qengine.py プロジェクト: ehchua/oasisqe
def test_html_esc():
    """ Check that our HTML escaping works ok. ( & -> &amp;  etc)
    """

    assert "&amp;" == General.htmlesc("&")
    assert "&lt;" == General.htmlesc("<")
    assert "&gt;" == General.htmlesc(">")
コード例 #5
0
ファイル: Practice.py プロジェクト: colincoghill/oasisqe
def mark_q(user_id, topic_id, q_id, request):
    """Mark the question and return the results"""
    answers = {}
    for i in request.form.keys():
        part = re.search(r"^Q_(\d+)_ANS_(\d+)$", i)
        if part:
            newqid = int(part.groups()[0])
            part = int(part.groups()[1])
            if newqid == q_id:
                value = request.form[i]
                answers["G%d" % part] = value
                DB.save_guess(newqid, part, value)
            else:
                L.warn("received guess for wrong question? (%d,%d,%d,%s)" %
                       (user_id, topic_id, q_id, request.form))
    try:
        marks = General.mark_q(q_id, answers)
        DB.set_q_status(q_id, 3)    # 3 = marked
        DB.set_q_marktime(q_id)
    except OaMarkerError:
        L.warn("Marker Error - (%d, %d, %d, %s)" %
               (user_id, topic_id, q_id, request.form))
        marks = {}
    q_body = General.render_mark_results(q_id, marks)
    parts = [int(var[1:])
             for var in marks.keys()
             if re.search(r"^A([0-9]+)$", var) > 0]
    parts.sort()
    total = 0.0
    for part in parts:
        if 'M%d' % (part,) in marks:
            total += float(marks['M%d' % (part,)])
    DB.update_q_score(q_id, total)    # 3 = marked
    DB.set_q_status(q_id, 2)
    return q_body
コード例 #6
0
ファイル: test_qengine.py プロジェクト: tkanesh/oasisqe
def test_html_esc():
    """ Check that our HTML escaping works ok. ( & -> &amp;  etc)
    """

    assert "&amp;" == General.htmlesc("&")
    assert "&lt;" == General.htmlesc("<")
    assert "&gt;" == General.htmlesc(">")
コード例 #7
0
ファイル: Assess.py プロジェクト: ehchua/oasisqe
def mark_exam(user_id, exam_id):
    """ Submit the assessment and mark it.
        Returns True if it went well, or False if a problem.
    """
    numquestions = Exams.get_num_questions(exam_id)
    status = Exams.get_user_status(user_id, exam_id)
    L.info("Marking assessment %s for %s, status is %s" %
           (exam_id, user_id, status))
    examtotal = 0.0
    errors = 0
    for position in range(1, numquestions + 1):
        q_id = General.get_exam_q(exam_id, position, user_id)
        if not q_id:
            L.critical(
                "Unable to retrieve exam question page %s, exam %s, for user %s"
                % (position, exam_id, user_id))
            errors += 1
            continue
        answers = DB.get_q_guesses(q_id)
        # There's a small chance they got here without ever seeing a question,
        # make sure it exists.
        DB.add_exam_q(user_id, exam_id, q_id, position)

        # First, mark the question
        try:
            marks = General.mark_q(q_id, answers)
            DB.set_q_status(q_id, 3)  # 3 = marked
            DB.set_q_marktime(q_id)
        except OaMarkerError:
            L.warn("Marker Error in question %s, exam %s, student %s!" %
                   (q_id, exam_id, user_id))
            return False
        parts = [
            int(var[1:]) for var in marks.keys()
            if re.search("^A([0-9]+)$", var) > 0
        ]
        parts.sort()

        # Then calculate the mark
        total = 0.0
        for part in parts:
            try:
                mark = float(marks['M%d' % (part, )])
            except (KeyError, ValueError):
                mark = 0
            total += mark
            DB.update_q_score(q_id, total)
        examtotal += total
    if not errors:
        Exams.set_user_status(user_id, exam_id, 5)
        Exams.set_submit_time(user_id, exam_id)
        Exams.save_score(exam_id, user_id, examtotal)
        Exams.touchuserexam(exam_id, user_id)

    if errors:
        return False
    L.info("user %s scored %s total on exam %s" %
           (user_id, examtotal, exam_id))
    return True
コード例 #8
0
ファイル: Assess.py プロジェクト: colincoghill/oasisqe
def mark_exam(user_id, exam_id):
    """ Submit the assessment and mark it.
        Returns True if it went well, or False if a problem.
    """
    numquestions = Exams.get_num_questions(exam_id)
    status = Exams.get_user_status(user_id, exam_id)
    L.info("Marking assessment %s for %s, status is %s" % (exam_id, user_id, status))
    examtotal = 0.0
    errors = 0
    for position in range(1, numquestions + 1):
        q_id = General.get_exam_q(exam_id, position, user_id)
        if not q_id:
            L.critical("Unable to retrieve exam question page %s, exam %s, for user %s" % (position, exam_id, user_id
                                                                                           )
                       )
            errors += 1
            continue
        answers = DB.get_q_guesses(q_id)
        # There's a small chance they got here without ever seeing a question,
        # make sure it exists.
        DB.add_exam_q(user_id, exam_id, q_id, position)

        # First, mark the question
        try:
            marks = General.mark_q(q_id, answers)
            DB.set_q_status(q_id, 3)    # 3 = marked
            DB.set_q_marktime(q_id)
        except OaMarkerError:
            L.warn("Marker Error in question %s, exam %s, student %s!" %
                   (q_id, exam_id, user_id))
            return False
        parts = [int(var[1:])
                 for var in marks.keys()
                 if re.search("^A([0-9]+)$", var) > 0]
        parts.sort()

        # Then calculate the mark
        total = 0.0
        for part in parts:
            try:
                mark = float(marks['M%d' % (part,)])
            except (KeyError, ValueError):
                mark = 0
            total += mark
            DB.update_q_score(q_id, total)
        examtotal += total
    if not errors:
        Exams.set_user_status(user_id, exam_id, 5)
        Exams.set_submit_time(user_id, exam_id)
        Exams.save_score(exam_id, user_id, examtotal)
        Exams.touchuserexam(exam_id, user_id)

    if errors:
        return False
    L.info("user %s scored %s total on exam %s" %
           (user_id, examtotal, exam_id))
    return True
コード例 #9
0
ファイル: views_cadmin.py プロジェクト: tkanesh/oasisqe
def cadmin_exam_viewmarked(course_id, exam_id, student_uid):
    """  Show a student's marked assessment results """

    course = Courses2.get_course(course_id)
    try:
        exam = Exams.get_exam_struct(exam_id, course_id)
    except KeyError:
        exam = {}
        abort(404)
    results, examtotal = Assess.render_own_marked_exam(student_uid, exam_id)

    if examtotal is False:
        status = 0
    else:
        status = 1
    marktime = Exams.get_mark_time(exam_id, student_uid)
    firstview = Exams.get_student_start_time(exam_id, student_uid)
    submittime = Exams.get_submit_time(exam_id, student_uid)

    try:
        datemarked = General.human_date(marktime)
    except AttributeError:
        datemarked = None
    try:
        datefirstview = General.human_date(firstview)
    except AttributeError:
        datefirstview = None
    try:
        datesubmit = General.human_date(submittime)
    except AttributeError:
        datesubmit = None

    user = Users2.get_user(student_uid)

    if submittime and firstview:
        taken = submittime-firstview
        takenmins = (taken.seconds/60)
    else:
        takenmins = None

    return render_template(
        "cadmin_markedresult.html",
        course=course,
        exam=exam,
        results=results,
        examtotal=examtotal,
        datesubmit=datesubmit,
        datemarked=datemarked,
        datefirstview=datefirstview,
        taken=takenmins,
        user=user,
        status=status
    )
コード例 #10
0
ファイル: test_qengine.py プロジェクト: ehchua/oasisqe
def test_date_ops():
    """ Test our various date operations
    """

    a = datetime.date(2013, 12, 1)
    b = datetime.date(2013, 12, 2)
    c = datetime.date(2013, 11, 1)
    d = datetime.date(2012, 11, 1)

    assert General.is_between(a, c, b) is True
    assert General.is_between(a, b, c) is True
    assert General.is_between(a, c, d) is False
コード例 #11
0
ファイル: test_qengine.py プロジェクト: tkanesh/oasisqe
def test_date_ops():
    """ Test our various date operations
    """

    a = datetime.date(2013, 12, 1)
    b = datetime.date(2013, 12, 2)
    c = datetime.date(2013, 11, 1)
    d = datetime.date(2012, 11, 1)

    assert General.is_between(a, c, b) is True
    assert General.is_between(a, b, c) is True
    assert General.is_between(a, c, d) is False
コード例 #12
0
ファイル: views_cadmin.py プロジェクト: ehchua/oasisqe
def cadmin_exam_viewmarked(course_id, exam_id, student_uid):
    """  Show a student's marked assessment results """

    course = Courses2.get_course(course_id)
    try:
        exam = Exams.get_exam_struct(exam_id, course_id)
    except KeyError:
        exam = {}
        abort(404)
    results, examtotal = Assess.render_own_marked_exam(student_uid, exam_id)

    if examtotal is False:
        status = 0
    else:
        status = 1
    marktime = Exams.get_mark_time(exam_id, student_uid)
    firstview = Exams.get_student_start_time(exam_id, student_uid)
    submittime = Exams.get_submit_time(exam_id, student_uid)

    try:
        datemarked = General.human_date(marktime)
    except AttributeError:
        datemarked = None
    try:
        datefirstview = General.human_date(firstview)
    except AttributeError:
        datefirstview = None
    try:
        datesubmit = General.human_date(submittime)
    except AttributeError:
        datesubmit = None

    user = Users2.get_user(student_uid)

    if submittime and firstview:
        taken = submittime - firstview
        takenmins = (taken.seconds / 60)
    else:
        takenmins = None

    return render_template("cadmin_markedresult.html",
                           course=course,
                           exam=exam,
                           results=results,
                           examtotal=examtotal,
                           datesubmit=datesubmit,
                           datemarked=datemarked,
                           datefirstview=datefirstview,
                           taken=takenmins,
                           user=user,
                           status=status)
コード例 #13
0
def setup_usersummary(view_id):
    """ Show an account summary for the given user account. """
    user_id = session['user_id']

    if not check_perm(user_id, -1, "useradmin"):
        flash("You do not have User Administration access.")
        return redirect(url_for('setup_top'))

    is_sysadmin = check_perm(user_id, -1, 'sysadmin')

    user = Users2.get_user(view_id)
    examids = Exams.get_exams_done(view_id)
    exams = []
    for examid in examids:
        exam = Exams.get_exam_struct(examid)
        started = General.human_date(exam['start'])
        exam['started'] = started

        exam['viewable'] = satisfy_perms(user_id, exam['cid'], ("viewmarks", ))

        exams.append(exam)
    exams.sort(key=lambda x: x['start_epoch'], reverse=True)

    course_ids = Users2.get_courses(view_id)
    courses = []
    for course_id in course_ids:
        courses.append(Courses2.get_course(course_id))

    user_is_admin = check_perm(view_id, 0, 'sysadmin')
    return render_template('setup_usersummary.html',
                           user=user,
                           exams=exams,
                           courses=courses,
                           is_sysadmin=is_sysadmin,
                           user_is_admin=user_is_admin)
コード例 #14
0
ファイル: test_topics.py プロジェクト: colincoghill/oasisqe
    def test_do_question(self):
        """ Do a question"""

        course_id = Courses.create("TEST102", "Test question logic", 1, 1)
        self.assertGreater(course_id, 0)
        topic1_id = Topics.create(course_id, "TESTQUESTIONS1", 1, 2)
        self.assertGreater(topic1_id, 0)

        qt1_id = DB.create_qt(1, "TESTQ9", "Test question 9", 0, 5.0, 1, topic_id=topic1_id)
        self.assertIsNotNone(qt1_id)

        ver = DB.get_qt_version(qt1_id)
        self.assertGreater(ver, 0)

        data = "2\n|1\n|2\n"
        qvars = [{'A1': "2"}, {'A1': "3"}]
        for row in range(0, len(qvars)):
            DB.add_qt_variation(qt1_id, row + 1, qvars[row], ver)
        DB.create_qt_att(qt1_id, "datfile.dat", "text/plain", data , ver)
        DB.create_qt_att(qt1_id, "qtemplate.html", "text/html", "What is <VAL A1>? <ANSWER 1>", ver)

        q_id = DB.get_q_by_qt_student(qt1_id, 1)
        self.assertFalse(q_id)  # Not generated yet

        q_id = General.gen_q(qt1_id, 1)
        self.assertGreater(q_id, 0)

        q_id = DB.get_q_by_qt_student(qt1_id, 1)
        self.assertTrue(qt1_id)  # Better be there now

        DB.update_qt_maxscore(qt1_id, 7.0)
        score = DB.get_qt_maxscore(qt1_id)
        self.assertEqual(score, 7.0)
        DB.set_q_viewtime(q_id)
        self.assertIsNotNone(DB.get_q_viewtime(q_id))
コード例 #15
0
def get_q_list(topic):
    """
    Return a list of questions, sorted by position.
    """

    # TODO: Duplicated in General.get_q_list ?

    def cmp_question_position(a, b):
        """Order questions by the absolute value of their positions
           since we use -'ve to indicate hidden.
        """
        return cmp(abs(a['position']), abs(b['position']))

    questionlist = General.get_q_list(topic, None, False)
    if questionlist:
        # At the moment we use -'ve positions to indicate that a question is
        # hidden but when displaying them we want to maintain the sort order.
        for question in questionlist:
            # Usually questions with position 0 are broken or uninteresting
            # so put them at the bottom.
            if question['position'] == 0:
                question['position'] = -10000
        questionlist.sort(cmp_question_position)
    else:
        questionlist = []

    return questionlist
コード例 #16
0
ファイル: API.py プロジェクト: colincoghill/oasisqe
def get_q_list(topic_id):
    """
    Return a list of questions, sorted by position.
    """
    # TODO: Duplicated in General.get_q_list ?

    def cmp_question_position(a, b):
        """Order questions by the absolute value of their positions
           since we use -'ve to indicate hidden.
        """
        return cmp(abs(a['position']), abs(b['position']))

    questionlist = General.get_q_list(topic_id, None, False)
    if questionlist:
        # At the moment we use -'ve positions to indicate that a question is
        # hidden but when displaying them we want to maintain the sort order.
        for question in questionlist:
            # Usually questions with position 0 are broken or uninteresting
            # so put them at the bottom.
            if question['position'] == 0:
                question['position'] = -10000
        questionlist.sort(cmp_question_position)
    else:
        questionlist = []

    return questionlist
コード例 #17
0
ファイル: Practice.py プロジェクト: ehchua/oasisqe
def get_sorted_questions(course_id, topic_id, user_id=None):
    """ Return a list of questions, sorted by position
    """

    def cmp_question_position(a, b):
        """Order questions by the absolute value of their positions
           since we use -'ve to indicate hidden.
        """
        return cmp(abs(a['position']), abs(b['position']))

    questionlist = General.get_q_list(topic_id, user_id, numdone=False)
    if questionlist:
        # Filter out the questions without a positive position unless
        # the user has prevew permission.
        canpreview = check_perm(user_id, course_id, "questionpreview")
        if not canpreview:
            questionlist = [question for question in questionlist
                            if question['position'] > 0]
        else:
            # At the moment we use -'ve positions to indicate that a question
            # is hidden but when displaying them we want to maintain the sort
            # order.
            for question in questionlist:
                # Usually questions with position 0 are broken or
                # uninteresting so put them at the bottom.
                if question['position'] == 0:
                    question['position'] = -10000
            questionlist.sort(cmp_question_position)
    else:
        questionlist = []
    return questionlist
コード例 #18
0
ファイル: Practice.py プロジェクト: colincoghill/oasisqe
def get_sorted_questions(course_id, topic_id, user_id=None):
    """ Return a list of questions, sorted by position
    """

    def cmp_question_position(a, b):
        """Order questions by the absolute value of their positions
           since we use -'ve to indicate hidden.
        """
        return cmp(abs(a['position']), abs(b['position']))

    questionlist = General.get_q_list(topic_id, user_id, numdone=False)
    if questionlist:
        # Filter out the questions without a positive position unless
        # the user has prevew permission.
        canpreview = check_perm(user_id, course_id, "questionpreview")
        if not canpreview:
            questionlist = [question for question in questionlist
                            if question['position'] > 0]
        else:
            # At the moment we use -'ve positions to indicate that a question
            # is hidden but when displaying them we want to maintain the sort
            # order.
            for question in questionlist:
                # Usually questions with position 0 are broken or
                # uninteresting so put them at the bottom.
                if question['position'] == 0:
                    question['position'] = -10000
            questionlist.sort(cmp_question_position)
    else:
        questionlist = []
    return questionlist
コード例 #19
0
ファイル: Practice.py プロジェクト: ehchua/oasisqe
def get_next_prev(qt_id, topic_id):
    """ Find the "next" and "previous" qtemplates, by topic, position. """
    if not topic_id:
        return None, None
        # This is very inefficient, but with the way questions are stored,
        # I didn't see a better way. Could maybe be revisited some time?
    questionlist = General.get_q_list(topic_id, numdone=False)
    if questionlist:
        # Filter out the questions without a positive position
        questionlist = [question
                        for question in questionlist
                        if question['position'] > 0]
    else:
        questionlist = []
        # We need to step through the list finding the "next and previous" id's
    nextid = None
    foundprev = None
    previd = None
    foundcurrent = None
    for i in questionlist:
        if foundcurrent:
            nextid = int(i['qtid'])
            break
        if int(i['qtid']) == int(qt_id):
            foundprev = True
            foundcurrent = True
        if not foundprev:
            previd = int(i['qtid'])
        # previd and nextid should now contain the correct values
    # or None, if they are not valid (current_qtid is the first or
    # last question)
    return previd, nextid
コード例 #20
0
ファイル: Embed.py プロジェクト: jamesdoherty/oasisqe
def mark_q(user_id, qtid, request):
    """Mark the question and show a page containing marking results."""

    if "OaQID" in request.form:
        qid = int(request.form["OaQID"])
    else:
        qid = None

    out = u""
    answers = {}
    for i in request.form.keys():
        part = re.search(r"^Q_(\d+)_ANS_(\d+)$", i)
        if part:
            newqid = int(part.groups()[0])
            part = int(part.groups()[1])

            value = request.form[i]
            answers["G%d" % part] = value
            DB.save_guess(newqid, part, value)

    if qid:
        try:
            marks = General.mark_q(qid, answers)
            DB.set_q_status(qid, 3)    # 3 = marked
            DB.set_q_marktime(qid)
        except OaMarkerError:
            log(INFO,
                "getMarkQuestionPage(%d, %d, %s) Marker ERROR" %
                (user_id, qtid, request.form))
            marks = {}

        out += General.render_mark_results(qid, marks)
        parts = [int(var[1:])
                 for var in marks.keys()
                 if re.search("^A([0-9]+)$", var) > 0]
        parts.sort()
        total = 0.0
        for part in parts:
            if marks.has_key('M%d' % (part,)):
                total += float(marks['M%d' % (part,)])

    return out
コード例 #21
0
def mark_q(user_id, qtid, request):
    """Mark the question and show a page containing marking results."""

    if "OaQID" in request.form:
        qid = int(request.form["OaQID"])
    else:
        qid = None

    out = u""
    answers = {}
    for i in request.form.keys():
        part = re.search(r"^Q_(\d+)_ANS_(\d+)$", i)
        if part:
            newqid = int(part.groups()[0])
            part = int(part.groups()[1])

            value = request.form[i]
            answers["G%d" % part] = value
            DB.save_guess(newqid, part, value)

    if qid:
        try:
            marks = General.mark_q(qid, answers)
            DB.set_q_status(qid, 3)  # 3 = marked
            DB.set_q_marktime(qid)
        except OaMarkerError:
            L.info("getMarkQuestionPage(%d, %d, %s) Marker ERROR" %
                   (user_id, qtid, request.form))
            marks = {}

        out += General.render_mark_results(qid, marks)
        parts = [
            int(var[1:]) for var in marks.keys()
            if re.search("^A([0-9]+)$", var) > 0
        ]
        parts.sort()
        total = 0.0
        for part in parts:
            if ('M%d' % part) in marks:
                total += float(marks['M%d' % (part, )])

    return out
コード例 #22
0
ファイル: test_qengine.py プロジェクト: ehchua/oasisqe
def test_instance_generate_multi_answer():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on multi "ANSWER MULTI"

        No side effects.
    """

    tmpl = "blah<ANSWER1 MULTI f,g,h,i>blah"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33}
    html = """<table border=0><tr><th>Please choose one:</th><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='1' Oa_CHK_1_1> 7</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='2' Oa_CHK_1_2> joe</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='3' Oa_CHK_1_3> 3.4</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='4' Oa_CHK_1_4> 33</td></tr></table><br />\n"""
    res = General.handle_multi(tmpl, 1, qvars, shuffle=False)[1]
    assert res == html
コード例 #23
0
ファイル: test_qengine.py プロジェクト: tkanesh/oasisqe
def test_instance_generate_multi_answer():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on multi "ANSWER MULTI"

        No side effects.
    """

    tmpl = "blah<ANSWER1 MULTI f,g,h,i>blah"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33}
    html = """<table border=0><tr><th>Please choose one:</th><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='1' Oa_CHK_1_1> 7</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='2' Oa_CHK_1_2> joe</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='3' Oa_CHK_1_3> 3.4</td><td CLASS='multichoicecell'><INPUT class='auto_save' TYPE='radio' NAME='ANS_1' VALUE='4' Oa_CHK_1_4> 33</td></tr></table><br />\n"""
    res = General.handle_multi(tmpl, 1, qvars, shuffle=False)[1]
    assert res == html
コード例 #24
0
ファイル: test_qengine.py プロジェクト: tkanesh/oasisqe
def test_instance_generate_listbox_answer():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on listbox "ANSWER SELECT"

        No side effects.
    """

    tmpl = "blah<ANSWER1 SELECT f,g,h,i>blah"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33}
    html = """<SELECT class='auto_save' NAME='ANS_1'>Please choose:<OPTION VALUE='None'>--Choose--</OPTION><OPTION VALUE='1' Oa_SEL_1_1>7</OPTION><OPTION VALUE='2' Oa_SEL_1_2>joe</OPTION><OPTION VALUE='3' Oa_SEL_1_3>3.4</OPTION><OPTION VALUE='4' Oa_SEL_1_4>33</OPTION></SELECT>\n"""
    res = General.handle_listbox(tmpl, 1, qvars, shuffle=False)[1]
    assert res == html
コード例 #25
0
ファイル: test_qengine.py プロジェクト: ehchua/oasisqe
def test_instance_generate_listbox_answer():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on listbox "ANSWER SELECT"

        No side effects.
    """

    tmpl = "blah<ANSWER1 SELECT f,g,h,i>blah"
    qvars = {'f': 7, 'g': "joe", "h": "3.4", "i": 33}
    html = """<SELECT class='auto_save' NAME='ANS_1'>Please choose:<OPTION VALUE='None'>--Choose--</OPTION><OPTION VALUE='1' Oa_SEL_1_1>7</OPTION><OPTION VALUE='2' Oa_SEL_1_2>joe</OPTION><OPTION VALUE='3' Oa_SEL_1_3>3.4</OPTION><OPTION VALUE='4' Oa_SEL_1_4>33</OPTION></SELECT>\n"""
    res = General.handle_listbox(tmpl, 1, qvars, shuffle=False)[1]
    assert res == html
コード例 #26
0
def setup_useraudit(audit_id):
    """ Show all the audit entries for the given user account. """
    user_id = session['user_id']

    if not check_perm(user_id, -1, "useradmin"):
        flash("You do not have User Administration access.")
        return redirect(url_for('setup_top'))

    user = Users2.get_user(audit_id)
    audits = get_records_by_user(audit_id)
    for aud in audits:
        aud['humantime'] = General.human_date(aud['time'])
    return render_template('setup_useraudit.html', user=user, audits=audits)
コード例 #27
0
ファイル: test_qengine.py プロジェクト: ehchua/oasisqe
def test_instance_generate_variable():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on variable subs.

        No side effects.
    """

    tmpl = "The value is <VAL A>"
    qvars = {"A": 7, "a": 5, "Arthur": 3}
    html = """The value is 7"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "The value is <VAL A> <VAL Arthur>"
    qvars = {"A": 7, "a": 5, "Arthur": 3}
    html = """The value is 7 3"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "The value is <VAL A> <VAL Arthur>"
    qvars = {"A": "&amp;", "a": 5, "Arthur": 3}
    html = """The value is &amp; 3"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "The value is <VAL A> <VAL Arthur>"
    qvars = {"A": "<blink>annoying</blink>", "a": 5, "Arthur": 3}
    html = """The value is <blink>annoying</blink> 3"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "The value is <VAL A> <VAL Arthur>"
    qvars = {"A": u"\x9f", "a": 5, "Arthur": 3}
    html = u"""The value is \x9f 3"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html
コード例 #28
0
ファイル: test_qengine.py プロジェクト: tkanesh/oasisqe
def test_instance_generate_simple_answer():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on simple "ANSWER"

        No side effects.
    """

    tmpl = "blah<ANSWER1>blah"
    qvars = {}
    html = """blah<INPUT class='auto_save' TYPE='text' NAME='ANS_1' VALUE="VAL_1"/>blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "blah<ANSWER2>blah"
    qvars = {}
    html = """blah<INPUT class='auto_save' TYPE='text' NAME='ANS_2' VALUE="VAL_2"/>blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "foo<ANSWER1>blah<ANSWER2>blah"
    qvars = {}
    html = """foo<INPUT class='auto_save' TYPE='text' NAME='ANS_1' VALUE="VAL_1"/>blah<INPUT class='auto_save' TYPE='text' NAME='ANS_2' VALUE="VAL_2"/>blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html
コード例 #29
0
ファイル: test_qengine.py プロジェクト: ehchua/oasisqe
def test_instance_generate_simple_answer():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on simple "ANSWER"

        No side effects.
    """

    tmpl = "blah<ANSWER1>blah"
    qvars = {}
    html = """blah<INPUT class='auto_save' TYPE='text' NAME='ANS_1' VALUE="VAL_1"/>blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "blah<ANSWER2>blah"
    qvars = {}
    html = """blah<INPUT class='auto_save' TYPE='text' NAME='ANS_2' VALUE="VAL_2"/>blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "foo<ANSWER1>blah<ANSWER2>blah"
    qvars = {}
    html = """foo<INPUT class='auto_save' TYPE='text' NAME='ANS_1' VALUE="VAL_1"/>blah<INPUT class='auto_save' TYPE='text' NAME='ANS_2' VALUE="VAL_2"/>blah"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html
コード例 #30
0
ファイル: test_qengine.py プロジェクト: tkanesh/oasisqe
def test_instance_generate_variable():
    """ Convert some html templates + variables into resulting instance HTML
        and make sure it's doing it right. Focus on variable subs.

        No side effects.
    """

    tmpl = "The value is <VAL A>"
    qvars = {"A": 7, "a": 5, "Arthur": 3}
    html = """The value is 7"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "The value is <VAL A> <VAL Arthur>"
    qvars = {"A": 7, "a": 5, "Arthur": 3}
    html = """The value is 7 3"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "The value is <VAL A> <VAL Arthur>"
    qvars = {"A": "&amp;", "a": 5, "Arthur": 3}
    html = """The value is &amp; 3"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "The value is <VAL A> <VAL Arthur>"
    qvars = {"A": "<blink>annoying</blink>", "a": 5, "Arthur": 3}
    html = """The value is <blink>annoying</blink> 3"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html

    tmpl = "The value is <VAL A> <VAL Arthur>"
    qvars = {"A": u"\x9f", "a": 5, "Arthur": 3}
    html = u"""The value is \x9f 3"""
    res = General.gen_q_html(qvars, tmpl)
    assert res == html
コード例 #31
0
ファイル: views_setup.py プロジェクト: colincoghill/oasisqe
def setup_useraudit(audit_id):
    """ Show all the audit entries for the given user account. """
    user_id = session['user_id']

    if not check_perm(user_id, -1, "useradmin"):
        flash("You do not have User Administration access.")
        return redirect(url_for('setup_top'))

    user = Users2.get_user(audit_id)
    audits = get_records_by_user(audit_id)
    for aud in audits:
        aud['humantime'] = General.human_date(aud['time'])
    return render_template(
        'setup_useraudit.html',
        user=user,
        audits=audits
    )
コード例 #32
0
ファイル: Practice.py プロジェクト: colincoghill/oasisqe
def get_practice_q(qt_id, user_id):
    """ Find an existing, or create a new, practice question
        for the given user."""
    try:
        qt_id = int(qt_id)
        assert qt_id > 0
    except (ValueError, TypeError, AssertionError):
        L.warn("Called with bad qtid %s?" % qt_id)
    qid = DB.get_q_by_qt_student(qt_id, user_id)
    if qid is not False:
        return int(qid)
    qid = General.gen_q(qt_id, user_id)
    try:
        qid = int(qid)
    except (ValueError, TypeError):
        L.warn("generateQuestion(%s,%s) Fail: returned %s" % (qt_id, user_id, qid))
    else:
        DB.set_q_viewtime(qid)
    return qid
コード例 #33
0
ファイル: Practice.py プロジェクト: ehchua/oasisqe
def get_practice_q(qt_id, user_id):
    """ Find an existing, or create a new, practice question
        for the given user."""
    try:
        qt_id = int(qt_id)
        assert qt_id > 0
    except (ValueError, TypeError, AssertionError):
        L.warn("Called with bad qtid %s?" % qt_id)
    qid = DB.get_q_by_qt_student(qt_id, user_id)
    if qid is not False:
        return int(qid)
    qid = General.gen_q(qt_id, user_id)
    try:
        qid = int(qid)
    except (ValueError, TypeError):
        L.warn("generateQuestion(%s,%s) Fail: returned %s" % (qt_id, user_id, qid))
    else:
        DB.set_q_viewtime(qid)
    return qid
コード例 #34
0
ファイル: Assess.py プロジェクト: ehchua/oasisqe
def student_exam_duration(student, exam_id):
    """ How long did the assessment take.
        returns   starttime, endtime
        either could be None if it hasn't been started/finished
    """

    firstview = None

    examsubmit = Exams.get_submit_time(exam_id, student)
    questions = General.get_exam_qs(student, exam_id)

    # we're working out the first time the assessment was viewed is the
    # earliest time a question in it was viewed
    # It's possible (although unlikely) that they viewed a question
    # other than the first page, first.
    for question in questions:
        questionview = DB.get_q_viewtime(question)
        if firstview:
            if questionview < firstview:
                firstview = questionview
        else:
            firstview = questionview
    return firstview, examsubmit
コード例 #35
0
ファイル: Assess.py プロジェクト: colincoghill/oasisqe
def student_exam_duration(student, exam_id):
    """ How long did the assessment take.
        returns   starttime, endtime
        either could be None if it hasn't been started/finished
    """

    firstview = None

    examsubmit = Exams.get_submit_time(exam_id, student)
    questions = General.get_exam_qs(student, exam_id)

    # we're working out the first time the assessment was viewed is the
    # earliest time a question in it was viewed
    # It's possible (although unlikely) that they viewed a question
    # other than the first page, first.
    for question in questions:
        questionview = DB.get_q_viewtime(question)
        if firstview:
            if questionview < firstview:
                firstview = questionview
        else:
            firstview = questionview
    return firstview, examsubmit
コード例 #36
0
ファイル: views_setup.py プロジェクト: colincoghill/oasisqe
def setup_usersummary(view_id):
    """ Show an account summary for the given user account. """
    user_id = session['user_id']

    if not check_perm(user_id, -1, "useradmin"):
        flash("You do not have User Administration access.")
        return redirect(url_for('setup_top'))

    is_sysadmin = check_perm(user_id, -1, 'sysadmin')

    user = Users2.get_user(view_id)
    examids = Exams.get_exams_done(view_id)
    exams = []
    for examid in examids:
        exam = Exams.get_exam_struct(examid)
        started = General.human_date(exam['start'])
        exam['started'] = started

        exam['viewable'] = satisfy_perms(user_id, exam['cid'], ("viewmarks", ))

        exams.append(exam)
    exams.sort(key=lambda x: x['start_epoch'], reverse=True)

    course_ids = Users2.get_courses(view_id)
    courses = []
    for course_id in course_ids:
        courses.append(Courses.get_course(course_id))

    user_is_admin = check_perm(view_id, 0, 'sysadmin')
    return render_template(
        'setup_usersummary.html',
        user=user,
        exams=exams,
        courses=courses,
        is_sysadmin=is_sysadmin,
        user_is_admin=user_is_admin
    )
コード例 #37
0
def practice_do_question(topic_id, position):
    """ Show them a question and allow them to fill in some answers """
    user_id = session['user_id']
    try:
        course_id = Topics.get_course_id(topic_id)
    except KeyError:
        course_id = None
        abort(404)
    try:
        course = Courses2.get_course(course_id)
    except KeyError:
        course = None
        abort(404)
    topictitle = "UNKNOWN"
    try:
        topictitle = Topics.get_name(topic_id)
    except KeyError:
        abort(404)
    try:
        choices = DB.get_qtemplates_in_topic_position(topic_id, position)
    except KeyError:
        choices = None
        abort(404)

    if len(choices) == 1:
        qt_id = choices[0]
    elif len(choices) > 1:
        L.debug("Practice choosing random from: %s" % repr(choices))
        qt_id = random.choice(choices)
    else:
        L.warn("Access to non existent practice topic %s question %s" % (topic_id, position))
        return render_template(
            "practicequestionerror.html",
            mesg="Error accessing question.",
            topic_id=topic_id,
            course=course,
            q_pos=position
        )

    qtemplate = DB.get_qtemplate(qt_id)

    questions = Practice.get_sorted_questions(course_id, topic_id, user_id)
    q_title = qtemplate['title']
    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,
        )

    try:
        q_id = Practice.get_practice_q(qt_id, user_id)
    except (ValueError, TypeError) as err:
        L.error("ERROR 1001  (%s,%s) %s" % (qt_id, user_id, err))
        return render_template(
            "practicequestionerror.html",
            mesg="Error generating question.",
            topictitle=topictitle,
            topic_id=topic_id,
            qt_id=qt_id,
            course=course,
            q_title=q_title,
            questions=questions,
            q_pos=q_pos,
        )

    if not q_id > 0:
        L.error("ERROR 1002  (%s,%s) Question not generated" % (qt_id, user_id))
        return render_template(
            "practicequestionerror.html",
            mesg="Error generating question.",
            topictitle=topictitle,
            topic_id=topic_id,
            qt_id=qt_id,
            course=course,
            q_title=q_title,
            questions=questions,
            q_pos=q_pos,
        )

    q_body = General.render_q_html(q_id)
    q_body = q_body.replace(r"\240", u" ")  # TODO: why is this here?

    return render_template(
        "practicedoquestion.html",
        q_body=q_body,
        topictitle=topictitle,
        topic_id=topic_id,
        qt_id=qt_id,
        course=course,
        q_title=q_title,
        questions=questions,
        q_pos=q_pos,
        q_id=q_id,
    )
コード例 #38
0
        )

    if not q_id > 0:
        return render_template(
            "practicequestionerror.html",
            mesg="Error generating question.",
            topictitle=topictitle,
            topic_id=topic_id,
            qt_id=qt_id,
            course=course,
            q_title=q_title,
            questions=questions,
            q_pos="?",
        )

    q_body = General.render_q_html(q_id)
    q_body = q_body.replace(r"\240", u" ")  # TODO: why is this here?

    return render_template(
        "practicedoquestion.html",
        q_body=q_body,
        topictitle=topictitle,
        topic_id=topic_id,
        qt_id=qt_id,
        course=course,
        q_title=q_title,
        questions=questions,
        q_pos=q_pos,
        q_id=q_id,
    )
コード例 #39
0
ファイル: Practice.py プロジェクト: colincoghill/oasisqe
def get_sorted_qlist_wstats(course_id, topic_id, user_id=None):
    """ Return a list of questions, sorted by position. With
        some statistics (may be expensive to calculate).
    """
    def cmp_question_position(a, b):
        """Order questions by the absolute value of their positions
           since we use -'ve to indicate hidden.
        """
        return cmp(abs(a['position']), abs(b['position']))

    questionlist = General.get_q_list(topic_id, user_id, numdone=False)
    if not questionlist:
        return []
        # Filter out the questions without a positive position unless
    # the user has prevew permission.
    questions = [question for question in questionlist
                 if question['position'] > 0]
    questions.sort(cmp_question_position)
    for question in questions:
        try:
            question['maxscore'] = DB.get_qt_maxscore(question['qtid'])
        except KeyError:
            question['maxscore'] = 0

        stats_1 = DB.get_student_q_practice_stats(user_id, question['qtid'], 3)
        if stats_1:  # Last practices
            # Date of last practice
            question['age'] = stats_1[(len(stats_1) - 1)]['age']
            question['ageseconds'] = stats_1[(len(stats_1) - 1)]['ageseconds']
            # Fetch last three scores and rate them as good, average or poor
            for attempt in stats_1:
                if question['maxscore'] > 0:
                    attempt['pscore'] = "%d%%" % ((attempt['score'] / question['maxscore']) * 100,)
                    attempt['rating'] = 2  # average
                    if attempt['score'] == question['maxscore']:
                        attempt['rating'] = 3  # good
                    if attempt['score'] == 0:
                        attempt['rating'] = 1  # poor

                else:  # don't have maxscore so don't make score a percentage
                    attempt['pscore'] = "%2.1f " % (attempt['score'],)
                    if attempt['score'] == 0:
                        attempt['rating'] = 1
            question['stats'] = stats_1
        else:
            question['stats'] = None
        stats_2 = DB.get_q_stats_class(course_id, question['qtid'])
        if not stats_2:  # no stats, make some up
            stats_2 = {'num': 0, 'max': 0, 'min': 0, 'avg': 0}
            percentage = 0
        else:
            if stats_2['max'] == 0:
                percentage = 0
            else:
                percentage = int(stats_2['avg'] / stats_2['max'] * 100)
        question['classpercent'] = str(percentage) + "%"
        user_stats = DB.get_prac_stats_user_qt(user_id, question['qtid'])
        if not user_stats:
            indivpercentage = 0
        else:
            if stats_2['max'] == 0:
                indivpercentage = 0
            else:
                indivpercentage = int(user_stats['avg'] / stats_2['max'] * 100)
        question['indivpercent'] = str(indivpercentage) + "%"
    return questions
コード例 #40
0
ファイル: Assess.py プロジェクト: colincoghill/oasisqe
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
コード例 #41
0
ファイル: Practice.py プロジェクト: ehchua/oasisqe
def get_sorted_qlist_wstats(course_id, topic_id, user_id=None):
    """ Return a list of questions, sorted by position. With
        some statistics (may be expensive to calculate).
    """
    def cmp_question_position(a, b):
        """Order questions by the absolute value of their positions
           since we use -'ve to indicate hidden.
        """
        return cmp(abs(a['position']), abs(b['position']))

    questionlist = General.get_q_list(topic_id, user_id, numdone=False)
    if not questionlist:
        return []
        # Filter out the questions without a positive position unless
    # the user has prevew permission.
    questions = [question for question in questionlist
                 if question['position'] > 0]
    questions.sort(cmp_question_position)
    for question in questions:
        try:
            question['maxscore'] = DB.get_qt_maxscore(question['qtid'])
        except KeyError:
            question['maxscore'] = 0

        stats_1 = DB.get_student_q_practice_stats(user_id, question['qtid'], 3)
        if stats_1:  # Last practices
            # Date of last practice
            question['age'] = stats_1[(len(stats_1) - 1)]['age']
            question['ageseconds'] = stats_1[(len(stats_1) - 1)]['ageseconds']
            # Fetch last three scores and rate them as good, average or poor
            for attempt in stats_1:
                if question['maxscore'] > 0:
                    attempt['pscore'] = "%d%%" % ((attempt['score'] / question['maxscore']) * 100,)
                    attempt['rating'] = 2  # average
                    if attempt['score'] == question['maxscore']:
                        attempt['rating'] = 3  # good
                    if attempt['score'] == 0:
                        attempt['rating'] = 1  # poor

                else:  # don't have maxscore so don't make score a percentage
                    attempt['pscore'] = "%2.1f " % (attempt['score'],)
                    if attempt['score'] == 0:
                        attempt['rating'] = 1
            question['stats'] = stats_1
        else:
            question['stats'] = None
        stats_2 = DB.get_q_stats_class(course_id, question['qtid'])
        if not stats_2:  # no stats, make some up
            stats_2 = {'num': 0, 'max': 0, 'min': 0, 'avg': 0}
            percentage = 0
        else:
            if stats_2['max'] == 0:
                percentage = 0
            else:
                percentage = int(stats_2['avg'] / stats_2['max'] * 100)
        question['classpercent'] = str(percentage) + "%"
        user_stats = DB.get_prac_stats_user_qt(user_id, question['qtid'])
        if not user_stats:
            indivpercentage = 0
        else:
            if stats_2['max'] == 0:
                indivpercentage = 0
            else:
                indivpercentage = int(user_stats['avg'] / stats_2['max'] * 100)
        question['indivpercent'] = str(indivpercentage) + "%"
    return questions
コード例 #42
0
ファイル: Assess.py プロジェクト: ehchua/oasisqe
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
コード例 #43
0
def practice_do_question_id(topic_id, qt_id):
    """ Show them a question and allow them to fill in some answers """
    user_id = session['user_id']
    try:
        course_id = Topics.get_course_id(topic_id)
    except KeyError:
        course_id = None
        abort(404)
    try:
        course = Courses2.get_course(course_id)
    except KeyError:
        course = None
        abort(404)
    topictitle = "UNKNOWN"
    try:
        topictitle = Topics.get_name(topic_id)
    except KeyError:
        abort(404)

    qtemplate = DB.get_qtemplate(qt_id)

    questions = Practice.get_sorted_questions(course_id, topic_id, user_id)
    q_title = qtemplate['title']
    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,
        )

    try:
        q_id = Practice.get_practice_q(qt_id, user_id)
    except (ValueError, TypeError) as err:
        L.error("ERROR 1001  (%s,%s) %s" % (qt_id, user_id, err))
        return render_template(
            "practicequestionerror.html",
            mesg="Error generating question.",
            topictitle=topictitle,
            topic_id=topic_id,
            qt_id=qt_id,
            course=course,
            q_title=q_title,
            questions=questions,
            q_pos=q_pos,
        )

    if not q_id > 0:
        L.error("ERROR 1002  (%s,%s) Question not generated" % (qt_id, user_id))
        return render_template(
            "practicequestionerror.html",
            mesg="Error generating question.",
            topictitle=topictitle,
            topic_id=topic_id,
            qt_id=qt_id,
            course=course,
            q_title=q_title,
            questions=questions,
            q_pos=q_pos,
        )

    q_body = General.render_q_html(q_id)
    q_body = q_body.replace(r"\240", u" ")  # TODO: why is this here?

    return render_template(
        "practicedoquestion.html",
        q_body=q_body,
        topictitle=topictitle,
        topic_id=topic_id,
        qt_id=qt_id,
        course=course,
        q_title=q_title,
        questions=questions,
        q_pos=q_pos,
        q_id=q_id,
    )