Exemplo n.º 1
0
def create_fill_in_the_blanks_widget(question, sections):

    question_widget = create_question_widget(question)
    num_sections = len(sections)

    paragraph = HBox([],
                     layout=Layout(display='flex',
                                   flex_flow='row wrap',
                                   align_items='stretch',
                                   width='auto'))
    for i in range(num_sections):
        section = sections[i]
        # Because row-wrap still not working. See https://stackoverflow.com/questions/58405678/text-wrapping-in-ipywidgets
        prefix = widgets.HTML(
            value='<style>p{word-wrap: break-word}</style> <p>' +
            section['prefix'] + ' </p>')
        #prefix = Label(value = section['prefix'], layout=Layout(width='auto'))
        blank = Text(value='',
                     placeholder='',
                     description='',
                     disabled=False,
                     layout=(Layout(width='auto')))

        suffix = widgets.HTML(
            value='<style>p{word-wrap: break-word}</style> <p>' +
            section['suffix'] + ' </p>')
        #suffix = Label(value=section['suffix'], layout=Layout(width='auto'))

        new_hbox = widgets.HBox([prefix, blank, suffix],
                                layout=Layout(display='flex',
                                              flex_flow='row wrap',
                                              align_items='stretch',
                                              width='auto'))

        # new_hbox.box_style = 'info'
        paragraph.children += (new_hbox, )

    # please G-d of programmers forgive me for I don't yet know how to get that colour from css.
    score_widget = create_score_widget('#4DD0E1')
    #    fill_in = AppLayout(header=question_widget,
    #                             left_sidebar=paragraph,
    #                             center=None,
    #                             right_sidebar=None,
    #                             footer=score_widget, layout=Layout(display='flex', flex_flow='column', #align_items='stretch', width='100%'))
    fill_in = VBox([question_widget, paragraph, score_widget],
                   layout=Layout(display='flex',
                                 flex_flow='column',
                                 align_items='stretch',
                                 width='100%'))

    fill_in.box_style = 'info'

    # compare checkbox value with original
    def check_answers(b):
        # run through each option, compare expected answer (checked/unchecked) with actual student answer
        num_sections = len(sections)
        incorrect = 0
        missing = 0

        paragraph_widget = fill_in.children[1]
        feedback_widget = fill_in.children[2]

        submit_button = feedback_widget.children[0]

        for i in range(num_sections):
            blank = paragraph_widget.children[i].children[1]

            actual_answer = blank.value
            expected_answer = sections[i]['answer']

            # clear feedback before giving new feedback
            blank.layout = Layout(border='None', width='auto', height='32px')

            # red border + 'incorrect' for incorrectly checked
            # green border + 'correct!' for correctly checked
            if (actual_answer == ''):
                missing += 1
            elif (expected_answer == actual_answer):
                blank.layout = Layout(border='1px solid #81C784',
                                      width='auto',
                                      height='31px')
            else:
                blank.layout = Layout(border='1px solid #e57373',
                                      width='auto',
                                      height='31px')
                incorrect += 1

        # update the score label
        if incorrect + missing == 0:
            # Success! So disable checkboxes
            for i in range(num_sections):
                blank = paragraph_widget.children[i].children[1]
                blank.disabled = True

            if submit_button.description == 'Submit':
                text = ''
            else:
                text = 'Now you got it!'

            generate_feedback(fill_in,
                              score_widget,
                              style='success',
                              feedback_text=text,
                              show_show_answer_btn=False)
            submit_button.layout.disable = True
        else:
            # Some incorrect answers, write feedback so they can try again
            if missing > 0:
                text = 'Fill in all the blanks!'
            else:
                text = ''

            generate_feedback(fill_in,
                              score_widget,
                              style='danger',
                              feedback_text=text,
                              show_show_answer_btn=True)

    def show_answers(b):
        num_sections = len(sections)

        paragraph_widget = fill_in.children[1]
        feedback_widget = fill_in.children[2]
        submit_button = feedback_widget.children[0]

        for i in range(num_sections):

            blank = paragraph_widget.children[i].children[1]
            # clear feedback before giving the answers
            blank.value = ''
            blank.layout = Layout(border='None', width='auto', height='32px')

            blank.placeholder = sections[i]['answer']

        generate_feedback(fill_in, score_widget, style='warning')

    submit_button = score_widget.children[0]
    submit_button.on_click(check_answers)
    show_answer_button = score_widget.children[2]
    show_answer_button.on_click(show_answers)

    return (fill_in)
Exemplo n.º 2
0
def create_multi_answer_widget(question, options):

    question_widget = create_question_widget(question)

    # Need to make my own checkbox out of checkbox + label because LaTeX not displaying nicely in checkbox built in description label

    labels = [
        widgets.HTML(value='<style>p{word-wrap: break-word}</style> <p>' +
                     option['answer'] + ' </p>') for option in options
    ]
    checkboxes = [
        HBox([
            Checkbox(value=False,
                     style={'description_width': 'initial'},
                     layout=Layout(width='30px')), lbl
        ],
             layout=Layout(display='flex',
                           flex_flow='row wrap',
                           align_items='stretch',
                           width='auto')) for lbl in labels
    ]

    # for each option, create a feedback box on the left and a checkbox on the right
    vertical = []
    for cb in checkboxes:
        new_hbox = widgets.HBox([Label(value=''), cb],
                                layout=Layout(display='flex',
                                              flex_flow='row wrap',
                                              align_items='stretch',
                                              width='auto'))
        #new_hbox.box_style = 'info'
        vertical.append(new_hbox)

    # vertically laid out options with feedback on the left
    option_widget = widgets.VBox(vertical,
                                 layout=Layout(display='flex',
                                               flex_flow='column',
                                               align_items='stretch',
                                               width='100%'))
    score_widget = create_score_widget('#4DD0E1')

    multi_answer = VBox([question_widget, option_widget, score_widget],
                        layout=Layout(display='flex',
                                      flex_flow='column',
                                      align_items='stretch',
                                      width='100%'))

    multi_answer.box_style = 'info'

    # compare checkbox value with original
    def check_answers(b):

        #run through each option, compare expected answer (checked/unchecked) with actual student answer
        num_options = len(options)
        incorrect = 0
        missing = 0

        option_widget = multi_answer.children[1]
        score_widget = multi_answer.children[2]

        submit_button = score_widget.children[0]

        for i in range(num_options):

            opt = option_widget.children[i]

            lbl = opt.children[0]
            cb = opt.children[1].children[0]

            actual_answer = cb.value
            expected_answer = options[i]['correct']

            # clear feedback before giving new feedback
            opt.layout = Layout(border=None)
            lbl.value = ''
            lbl.layout = Layout(width='100px')

            # red border + 'incorrect' for incorrectly checked
            # green border + 'correct!' for correctly checked
            if (expected_answer and actual_answer):
                opt.layout = Layout(border='1px solid #81C784')
                lbl.value = 'Correct!'
            if (expected_answer and not actual_answer):
                missing += 1
            if (not expected_answer and actual_answer):
                lbl.value = 'Incorrect'
                opt.layout = Layout(border='1px solid #e57373')
                incorrect += 1

        # update the score label
        if incorrect + missing == 0:
            # Success! So disable checkboxes
            for i in range(num_options):
                opt = option_widget.children[i]
                cb = opt.children[1].children[0]
                cb.disabled = True

            if submit_button.description == 'Submit':
                text = ''
            else:
                text = 'Now you got it!'

            generate_feedback(multi_answer,
                              score_widget,
                              style='success',
                              feedback_text=text,
                              show_show_answer_btn=False)
            submit_button.layout.disable = True
        else:
            #Some incorrect answers, write feedback so they can try again
            if missing > 0:
                text = 'You missed some correct options, try again!'
            else:
                text = ''

            generate_feedback(multi_answer,
                              score_widget,
                              style='danger',
                              feedback_text=text,
                              show_show_answer_btn=False)

    submit_button = score_widget.children[0]
    submit_button.on_click(check_answers)

    return (multi_answer)