コード例 #1
0
ファイル: forms.py プロジェクト: pombreda/socraticqs
def build_assess_form(q,
                      errorModels=(),
                      bottom='',
                      title='Assessing your answer'):
    'return HTML for standard form for round 2'
    doc = webui.Document(title)
    if getattr(q, 'showAnswer', False) and getattr(q, 'explanation', False):
        doc.add_text('Answer: ' + q.explanation, 'B')
        doc.add_text('<HR>\n')
    doc.add_text(
        '''How does your answer compare with the right answer?
    If your answer was different, please briefly explain below how your
    reasoning differed.''', 'B')
    form = webui.Form('submit')
    form.append(webui.Input('qid', 'hidden', str(q.id)))
    form.append(webui.Input('stage', 'hidden', 'assess'))
    options = (('correct', 'Essentially the same.'), ('close', 'Close.'),
               ('different', 'Different.'))
    form.append(webui.RadioSelection('assessment', options))
    if errorModels:
        form.append(
            "<br>\n<b>Did you make any of the following common errors?</b><br>\n"
        )
        form.append(
            webui.CheckboxSelection('errors', list(enumerate(errorModels))))
    form.append('''<br>\nIf you made an error not listed above, please
indicate how your reasoning differed from the right idea.  
Otherwise, you may leave this blank, or ask any question about
this problem that still puzzles you:<br>\n''')
    form.append(webui.Textarea('differences'))
    form.append('<br>\n')
    doc.append(form)
    doc.add_text(bottom)
    return str(doc)
コード例 #2
0
ファイル: forms.py プロジェクト: pombreda/socraticqs
def build_quizmode_form(formtitle='Switch to Quiz Mode?',
                        explanation='''Quiz Mode presents all questions
                        on a single form, so students answer them all
                        and then submit the form once.  This is
                        designed for giving the students a test
                        rather than the usual mode of walking
                        them through one exercise at a time.''',
                        title='Quiz',
                        instructions='''Please answer all of the following
                        questions. You must answer all questions.
                        When you have answered all questions, click Go
                        to submit your answers.  Note that your submitted
                        answers are final; you cannot resubmit answers again.'''
                        ):
    doc = webui.Document(formtitle)
    doc.add_text(explanation)
    form = webui.Form('quizmode')
    form.append('<br>\nQuiz Title:\n')
    form.append(webui.Input('title', value='Quiz', size=50))
    form.append('<br>\nInstructions for the students:<br>\n')
    form.append(webui.Textarea('instructions', value=instructions))
    form.append('<br>\nWill this quiz be graded?<br>\n')
    options = (('yes', 'Graded'), ('', 'Ungraded'))
    form.append(webui.RadioSelection('graded', options))
    form.append('<br>\n')
    doc.append(form)
    return str(doc)
コード例 #3
0
ファイル: forms.py プロジェクト: pombreda/socraticqs
def build_reconsider_form(qid, bottom='', title='Reconsidering your answer'):
    'return HTML for standard form for round 2'
    doc = webui.Document(title)
    doc.add_text('''<B>Instructions</B>: As soon as your partner is
    ready, please take turns explaining why you think your
    answer is right, approximately one minute each.
    Then answer the following questions:<BR>
    ''')
    form = webui.Form('submit')
    form.append(webui.Input('qid', 'hidden', str(qid)))
    form.append(webui.Input('stage', 'hidden', 'reconsider'))
    d = dict(
        unchanged='I still prefer my original answer.',
        switched=
        "I've decided my partner's answer is better (enter his/her name below)."
    )
    form.append(webui.RadioSelection('status', d.items(),
                                     selected='unchanged'))
    add_confidence_choice(form)
    form.append(
        "<br>\nYour partner's username (only needed if you prefer their answer):"
    )
    form.append(webui.Input('partner'))
    form.append('<br>\n')
    doc.append(form)
    doc.add_text(bottom)
    return str(doc)
コード例 #4
0
ファイル: question.py プロジェクト: pombreda/socraticqs
 def start_admin(self, starttimer=0, showresp=''):
     doc = webui.Document('Socraticqs Admin')
     doc.add_text(self.title, 'H1')
     doc.add_text(self.text, 'BIG')
     doc.add_text('<HR>\n')
     if starttimer:  # start the timer
         self.starttime = time.time()
     if hasattr(self, 'starttime'):  # show timer, progress stats
         elapsed = int(time.time() - self.starttime)
         doc.add_text('Time since start: %d:%02d' %
                      (elapsed / 60, elapsed % 60))
         doc.add_text(' (updates every %d sec)' % self.refresh)
         doc.add_text('<BR>\n')
         t = webui.Table('Student Answers So Far', (
             'Just guessing',
             'Not quite sure',
             'Pretty sure',
             '(not yet)',
         ))
         doc.append(t)
         if showresp:
             doc.add_text('<BR>\n(<A HREF="qadmin">hide answers</A>)<BR>\n')
         else:
             doc.add_text(
                 '<BR>\n(<A HREF="qadmin?showresp=1">show answers</A>)<BR>\n'
             )
         counts = [0, 0, 0]
         for r in self.responses.values():
             if showresp:
                 doc.add_text(str(r), 'LI')
             counts[r.confidence] += 1
         counts.append(len(self.courseDB.logins) - len(self.responses))
         t.append(counts)
         doc.add_text('''<BR><B>Instructions</B>: when you feel
         enough students have responded (totally up to you), tell
         the students what stage to proceed to.  E.g. you could ask
         them to discuss their answer with their neighbor (and if you
         wish, tell them to click the DISCUSS link to report whether
         this changed their minds).  Or you could proceed directly
         to the ASSESS stage to present the solution and have the
         students self-assess.
         Note: you may use the navigation bar below to
         jump forward to another stage or question at any time.''')
         doc.head.append(
             '<meta http-equiv="Refresh" content="%d; url=qadmin?showresp=%s">\n'
             % (self.refresh, showresp))
     else:  # show instructions, GO button
         doc.add_text('''<B>Instructions</B>: present the question to the
         students.  When you tell them to start, click the Go button
         to begin the timer.
         For a concept test, typically give them a minute to think
         about the question, and a minute or two to enter an answer.''')
         form = webui.Form('qadmin')
         form.append(webui.Input('starttimer', 'hidden', '1'))
         doc.append(form)
     doc.add_text(self.server.admin_nav())
     return str(doc)
コード例 #5
0
ファイル: question.py プロジェクト: pombreda/socraticqs
 def assess_admin(self, showresp=''):
     if not getattr(self, 'showAnswer', False):
         self.showAnswer = True
         self._viewHTML['assess'] = \
             forms.build_assess_form(self, self.errorModels, self._navHTML)
     doc = webui.Document('Socraticqs Admin')
     doc.add_text(self.title + ' Answer', 'H1')
     if hasattr(self, 'correctAnswer'):
         doc.add_text(str(self.correctAnswer), 'BIG')
         doc.add_text('<HR>\n')
     doc.add_text(self.explanation, 'B')
     doc.add_text('<HR>\n')
     if hasattr(self, 'starttime'):  # show timer, progress stats
         elapsed = int(time.time() - self.starttime)
         doc.add_text('Time since start: %d:%02d' %
                      (elapsed / 60, elapsed % 60))
         doc.add_text(' (updates every %d sec)' % self.refresh)
         doc.add_text('<BR>\n')
         t = webui.Table('Self-Assessments So Far', (
             'Different',
             'Close',
             'Correct',
             '(not yet)',
         ))
         doc.append(t)
         if showresp:
             doc.add_text(
                 '<BR>\n(<A HREF="qassess">hide self-assessments</A>)<BR>\n'
             )
         else:
             doc.add_text(
                 '<BR>\n(<A HREF="qassess?showresp=1">show self-assessments</A>)<BR>\n'
             )
         counts = {}
         for r in self.responses.values():
             if showresp and getattr(r, 'criticisms', False):
                 doc.add_text(r.criticisms, 'LI')
             try:
                 counts[r.reasons] = counts.get(r.reasons, 0) + 1
             except AttributeError:
                 pass
         t.append((counts.get('different',
                              0), counts.get('close',
                                             0), counts.get('correct', 0),
                   len(self.responses) - sum(counts.values())))
         doc.add_text('''<BR><B>Instructions</B>:
         present the answer to the students,
         and ask them to click ASSESS to enter their self-assessment.
         Note: you may click START below to
         jump forward to another question at any time.''')
         doc.head.append(
             '<meta http-equiv="Refresh" content="%d; url=qassess?showresp=%s">\n'
             % (self.refresh, showresp))
     doc.add_text(self.server.admin_nav())
     return str(doc)
コード例 #6
0
ファイル: question.py プロジェクト: pombreda/socraticqs
 def prototype_form(self,
                    offset=0,
                    maxview=None,
                    title='Categorize Responses'):
     offset = int(offset)
     unclustered = self.count_unclustered()
     if unclustered == 0:
         return self.cluster_report()
     doc = webui.Document(title)
     doc.add_text('''<B>Instructions</B>: if you wish, you can choose
     individual responses as distinct categories of answers, and
     then ask the students to assign themselves to these categories.
     However, this is purely <B>optional</B>.
     Click here to <A HREF="prototype_form">UPDATE</A> for the
     latest results.''')
     if self.categories:  # not empty
         doc.add_text('%d Categories' % len(self.categories), 'h1')
         for r in self.categories:
             if r == self.correctAnswer:
                 doc.add_text('<B>correct</B>: ' + str(r), 'LI')
             else:
                 doc.add_text(str(r), 'LI')
     doc.add_text('%d Uncategorized Responses' % unclustered, 'h1')
     doc.add_text('''Choose one or more responses as new, distinct
     categories of student answers:<br>
     ''')
     l = list(self.iter_unclustered())[offset:]
     if not maxview:
         try:
             maxview = self.maxview
         except AttributeError:
             maxview = 10
     maxview = int(maxview)
     if maxview and len(l) > maxview:
         l = l[:maxview]
     form = webui.Form('add_prototypes')
     for r in l:
         form.append(
             webui.RadioSelection('resp_' + str(r.uid),
                                  (('add', str(r)), )))
     doc.append(form)
     if offset > 0:
         doc.add_text(
             '<A HREF="prototype_form?offset=%d&maxview=%d">[Previous %d]</A>\n'
             % (max(0, offset - maxview), maxview, maxview))
     if maxview and unclustered > offset + maxview:
         doc.add_text(
             '<A HREF="prototype_form?offset=%d&maxview=%d">[Next %d]</A>\n'
             % (offset + maxview, maxview, maxview))
     doc.add_text('''<br>If you want to "declare victory", click here to
     proceed to the <A HREF="cluster_report">cluster report</A>.''')
     doc.add_text(self.server.admin_nav())
     return str(doc)
コード例 #7
0
ファイル: question.py プロジェクト: pombreda/socraticqs
 def build_vote_form(self,
                     form=None,
                     title='Vote for the best answer',
                     text='''<h1>Vote</h1>
                     Which of the following answers do you think is correct?
                     <br>'''):
     doc = webui.Document(title)
     doc.add_text(text)
     if form is None:
         form = self.get_choice_form()
     doc.append(form)
     doc.add_text(self._navHTML)
     return str(doc)
コード例 #8
0
ファイル: question.py プロジェクト: pombreda/socraticqs
    def analysis(self, title='Final Results'):
        if self.responses:
            f = 100. / len(self.responses)
        else:  # avoid division by zero error
            f = 1.

        def perc(d, k):
            return '%1.0f%%' % (d.get(k, 0) * f)

        doc = webui.Document(title)
        doc.add_text('''<B>Instructions</B>: This table shows the
        fraction of students that got the correct answer,
        or gave no response (NR).  Uncategorized responses are not
        shown.  Click here to <A HREF="analysis">UPDATE</A> for the
        latest results.''')
        d1, d2, d3 = self.count_rounds()
        t = webui.Table('%d Responses' % len(self.responses),
                        ('answer', 'initial', 'revised', 'final'))
        for i, category in enumerate(self.list_categories()):
            a = letters[i]
            if category == self.correctAnswer:  # bold the correct answer
                a = '<B>' + a + '</B> (correct)'
            t.append(
                (a, perc(d1, category), perc(d2, category), perc(d3,
                                                                 category)))
        t.append(('NR', '0%', perc(d2, None), perc(d3, None)))
        doc.append(t)
        doc.add_text('Reasons and Critiques', 'h1')
        for i, category in enumerate(self.categoriesSorted):
            doc.add_text('Answer ' + letters[i], 'h2')
            doc.add_text(str(category))
            if self.categories[category]:
                doc.add_text('Reasons Given for this Answer', 'h3')
                for r in self.categories[category]:
                    reasons = getattr(r, 'reasons', None)
                    if reasons:
                        doc.add_text(reasons, 'LI')
            l = []
            for r in self.responses.values():
                if getattr(r, 'critiqueTarget', None) == category \
                   and getattr(r, 'criticisms', None):
                    l.append(r.criticisms)
            if l:
                doc.add_text('Critiques of this Answer', 'h3')
                for s in l:
                    doc.add_text(s, 'LI')
            doc.add_text('<HR>\n')
        doc.add_text(self.server.admin_nav())
        return str(doc)
コード例 #9
0
ファイル: question.py プロジェクト: pombreda/socraticqs
 def build_self_critique_form(self,
                              title='Critique your original answer',
                              text='''<h1>Critique</h1>
                              Briefly state what you think was wrong with your original answer:
                              <br>''',
                              action='self_critique'):
     doc = webui.Document(title)
     doc.add_text(text)
     form = webui.Form('submit')
     form.append(webui.Input('qid', 'hidden', str(self.id)))
     form.append(webui.Input('stage', 'hidden', action))
     form.append(webui.Textarea('criticisms'))
     form.append('<br>\n')
     doc.append(form)
     doc.add_text(self._navHTML)
     return str(doc)
コード例 #10
0
ファイル: forms.py プロジェクト: pombreda/socraticqs
def login_form(
    action='login',
    text='Please login to Socraticqs using your username and Student ID:<br>\n',
    registerText='''<br>
               If you have never logged in, click here to
               <A HREF="register_form">register</A>.
               '''):
    doc = webui.Document('Login')
    doc.add_text(text)
    form = webui.Form(action)
    form.append(webui.Data('username:'******'username', size=10))
    form.append(webui.Data('<br>\nUID:'))
    form.append(webui.Input('uid', 'password', size=10))
    doc.append(form)
    doc.add_text(registerText)
    return str(doc)
コード例 #11
0
ファイル: question.py プロジェクト: pombreda/socraticqs
 def build_cluster_form(self, title='Cluster Your Answer'):
     doc = webui.Document(title)
     doc.add_text('''Either choose the answer that basically matches
     your original answer, or choose <B>None of the Above</B><br>
     ''')
     form = webui.Form('submit')
     form.append(webui.Input('qid', 'hidden', str(self.id)))
     form.append(webui.Input('stage', 'hidden', 'cluster'))
     l = []
     for i, r in enumerate(self.list_categories()):
         l.append((i, str(r)))
     l.append(('none', 'None of the above'))
     form.append(webui.RadioSelection('match', l))
     form.append('<br>\n')
     doc.append(form)
     doc.add_text(self._navHTML)
     return str(doc)
コード例 #12
0
 def _admin_page(self):
     doc = webui.Document('Socraticqs Console')
     doc.add_text('%d students logged in.' % len(self.courseDB.logins))
     doc.add_text('Concept Tests', 'h1')
     for i, q in enumerate(self.courseDB.questions):
         doc.add_text(
             '''<A HREF="start_question?q=%d"
         TITLE="Start the students on this question">%s</A>''' %
             (i, q.title), 'LI')
     doc.add_text('''<B>Instructions</B>: click on a question to start
     the students on that question.
     At any time you may use the navigation bar
     at the bottom of the page to go to whatever stage
     you wish.<BR>
     <BR>
     Or click here to switch to <A HREF="quiz_form">Quiz Mode</A>.''')
     doc.add_text(self.admin_nav())
     return str(doc)
コード例 #13
0
ファイル: forms.py プロジェクト: pombreda/socraticqs
def register_form(action='register',
                  text='''Please register by choosing a username, and
                  entering your full name and Student ID:<br>\n''',
                  loginText='''<br>
                  If you have already registered, click here to
                  <A HREF="login_form">login</A>.
                  '''):
    doc = webui.Document('Register')
    doc.add_text(text)
    form = webui.Form(action)
    form.append(webui.Data('username:'******'username', size=10))
    form.append(webui.Data('<br>\nFull Name (e.g. Joe Smith):'))
    form.append(webui.Input('fullname', size=20))
    form.append(webui.Data('<br>\nUID:'))
    form.append(webui.Input('uid', 'password', size=10))
    form.append(webui.Data('<br>\nRe-enter UID:'))
    form.append(webui.Input('uid2', 'password', size=10))
    doc.append(form)
    doc.add_text(loginText)
    return str(doc)
コード例 #14
0
ファイル: question.py プロジェクト: pombreda/socraticqs
 def cluster_report(self):
     fmt = '%(answer)s<br><b>(%(tag)s answer chosen by %(n)d students)</b>'
     doc = webui.Document('Clustering Complete')
     doc.add_text(
         'Done: %d responses in %d categories:' %
         (len(self.responses), len(self.categories)), 'h1')
     try:
         p = len(self.categories.get(self.correctAnswer, ())) * 100. \
             / len(self.responses)
     except AttributeError:
         doc.add_text('Choose which answer is correct:')
         doc.append(
             self.get_choice_form('correct', False, 0, fmt,
                                  useSubmit=False))
         doc.add_text('''<br>If none of these are correct, click here
         to add the <A HREF="add_correct">correct answer</A>
         given by the instructor.''')
     else:
         doc.add_text('%2.0f%% of students got the correct answer<hr>' % p)
         doc.append(self.get_choice_form('correct', False, 0, fmt))
         doc.add_text(self._gotoVoteHTML)
         self.init_vote()
     doc.add_text(self.server.admin_nav())
     return str(doc)
コード例 #15
0
ファイル: question.py プロジェクト: pombreda/socraticqs
 def __init__(self, questionID, title, text, explanation, nerror, *args,
              **kwargs):
     self.id = questionID
     self.title = title
     self.text = text
     self.explanation = explanation
     nerror = int(nerror)
     self.errorModels = args[:nerror]
     args = args[nerror:]  # skip past error models
     try:
         self.rootPath = kwargs['rootPath']
         del kwargs['rootPath']
     except KeyError:
         self.rootPath = ''
     self.refresh = 15
     self.categories = {}
     for attr in ('hasReasons', 'isClustered', 'noMatch', 'hasFinalVote',
                  'hasCritique'):
         setattr(self, attr, set())  # initialize answer counters
     doc = webui.Document(title)
     self.doc = doc
     doc.add_text(text)
     form = webui.Form('submit')
     form.append(webui.Input('qid', 'hidden', str(self.id)))
     form.append(webui.Input('stage', 'hidden', 'answer'))
     self.build_form(form, *args, **kwargs)
     try:
         self.correctAnswer.prototype = self.correctAnswer
     except AttributeError:
         pass
     doc.append(form)
     doc.add_text(self._navHTML)
     self.responses = {}
     d = {}
     for attr in self._stages:  # initialize submission action dict
         d[attr] = getattr(self, attr)
     self.submitStages = d
     self._afterURL = self.get_url('assess')
     self._viewHTML = {
         'answer': str(doc),
         'reconsider': forms.build_reconsider_form(questionID,
                                                   self._navHTML),
         'assess': '''Your instructor has not yet started the ASSESS phase.
         When your instructor asks you to, please click here to
         <A HREF="%s">ASSESS</A> your answer.%s''' \
         % (self.get_url('assess'), self._navHTML)
         }
     self._clusterFormHTML = \
         '''No categories have yet been added.
         When your instructor asks you to, please click here to
         continue to <A HREF="%s">categorize your answer</A>.%s''' \
         % (self.get_url('cluster'), self._navHTML)
     self._matchedHTML = \
         '''Your answer already matches a category.
         When your instructor asks you to, please click here to
         continue to the <A HREF="%s">final vote</A>.%s''' \
         % (self.get_url('vote'), self._navHTML)
     self._noResponseHTML = \
         '''Sorry, you first need to submit an answer
         to this question, because I can find no record of your
         answer.  Please click the START link below to continue.''' \
         + self._navHTML