<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Oysin</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Oysin"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Oysin"/>
	<updated>2026-07-12T13:01:54Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152481</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152481"/>
		<updated>2023-12-05T02:45:05Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Adding multiple_choice_radio_spec.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display`if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Add a new method &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; to check the validity of inputs (question and answer texts).&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are 2 correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution (Phase 1) ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
We created an additional rspec file &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; to enable testing for the MultipleChoiceRadio class. We included testing for all four methods (&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Why &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152478</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152478"/>
		<updated>2023-12-05T02:42:00Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Final Phase Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display`if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Add a new method &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; to check the validity of inputs (question and answer texts).&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are 2 correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution (Phase 1) ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== Why &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152477</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152477"/>
		<updated>2023-12-05T02:41:30Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display`if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Add a new method &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; to check the validity of inputs (question and answer texts).&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are 2 correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution (Phase 1) ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152474</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152474"/>
		<updated>2023-12-05T02:40:53Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* multiple_choice_checkbox.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display`if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Add a new method &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; to check the validity of inputs (question and answer texts).&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are 2 correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152470</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152470"/>
		<updated>2023-12-05T02:39:18Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Objectives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display`if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Add a new method &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; to check the validity of inputs (question and answer texts).&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152360</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152360"/>
		<updated>2023-12-04T21:18:17Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Objectives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Add a new method &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; to check the validity of inputs (question and answer texts).&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152359</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152359"/>
		<updated>2023-12-04T21:18:07Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Objectives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Add a new method &amp;lt;code&amp;gt;valid&amp;lt;/code&amp;gt; to check the validity of inputs (question and answer texts).&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152358</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152358"/>
		<updated>2023-12-04T21:17:58Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Objectives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Add a new method &amp;gt;code&amp;gt;valid&amp;lt;/code&amp;gt; to check the validity of inputs (question and answer texts).&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152357</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152357"/>
		<updated>2023-12-04T21:16:50Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* multiple_choice_radio.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152356</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152356"/>
		<updated>2023-12-04T21:09:19Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Testing HTML with Nokogiri */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt; where we broke down the original HTML string into smaller, more readable chunks for testing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152354</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152354"/>
		<updated>2023-12-04T21:08:47Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Testing HTML with Nokogiri */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. Here's an example from &amp;lt;code&amp;gt;true_false_spec.rb&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152353</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152353"/>
		<updated>2023-12-04T21:08:14Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Testing HTML with Nokogiri */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
Testing with Nokogiri in Rspec allows us to selectively query parsed HTML to inspect certain elements. This allows us to write more targeted tests. Moreover, it allows us to write readable and expressive tests that closely resemble the behavior of Expertiza. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152351</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152351"/>
		<updated>2023-12-04T21:05:47Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Final Phase Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
&amp;lt;b&amp;gt;Before refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre style =&amp;quot;white-space: pre-wrap;&amp;quot;&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt; Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot;  id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt; &amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;After refactoring:&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
# Test for presence of a text area for the question text&lt;br /&gt;
expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for presence of an input for the question weight&lt;br /&gt;
expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
# Test for the correct number of choices&lt;br /&gt;
expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152350</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152350"/>
		<updated>2023-12-04T20:58:26Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Testing HTML with Nokogiri */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt;Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot; id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&amp;lt;/pre&amp;gt; || &lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
      # Test for presence of a text area for the question text&lt;br /&gt;
      expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
      # Test for presence of an input for the question weight&lt;br /&gt;
      expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
      # Test for the correct number of choices&lt;br /&gt;
      expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152349</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152349"/>
		<updated>2023-12-04T20:57:53Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Final Phase Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
=== Testing HTML with Nokogiri ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;expect(true_false.edit).to eq('&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[1][txt]&amp;quot; id=&amp;quot;question_1_txt&amp;quot;&amp;gt;Test question:&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[1][txt]&amp;quot; id=&amp;quot;question_wt_1_txt&amp;quot; value=&amp;quot;1&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;True&amp;quot; checked=&amp;quot;checked&amp;quot; /&amp;gt;True&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;input type=&amp;quot;radio&amp;quot; name=&amp;quot;quiz_question_choices[1][TrueFalse][1][iscorrect]&amp;quot; id=&amp;quot;quiz_question_choices_1_TrueFalse_1_iscorrect_True&amp;quot; value=&amp;quot;False&amp;quot; /&amp;gt;False&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;')&amp;lt;/pre&amp;gt; || &lt;br /&gt;
&amp;lt;pre&amp;gt;html = Nokogiri::HTML(true_false.edit)&lt;br /&gt;
      # Test for presence of a text area for the question text&lt;br /&gt;
      expect(html.css('textarea[name=&amp;quot;question[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
      # Test for presence of an input for the question weight&lt;br /&gt;
      expect(html.css('input[name=&amp;quot;question_weights[1][txt]&amp;quot;]')).not_to be_empty&lt;br /&gt;
      # Test for the correct number of choices&lt;br /&gt;
      expect(html.css('input[type=&amp;quot;radio&amp;quot;][name^=&amp;quot;quiz_question_choices[1][TrueFalse]&amp;quot;]').size).to eq(2)&amp;lt;/pre&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Adding &amp;lt;code&amp;gt;multiple_choice_radio_spec.rb&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
=== An explaination of why isvalid cannot be added to &amp;lt;code&amp;gt;QuizQuestion&amp;lt;/code&amp;gt;'s superclass &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152348</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152348"/>
		<updated>2023-12-04T20:50:15Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Final Phase Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
==== changes to testing hard coded html -&amp;gt; Nokogiri ====&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152347</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152347"/>
		<updated>2023-12-04T20:49:42Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Final Phase Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object. Here's an example from QuizQuestion's &amp;lt;code&amp;gt;view_question_text&amp;gt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin:auto&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Before refactoring !! After refactoring&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = '&amp;lt;b&amp;gt;' + txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Type: ' + type + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  @html += 'Question Weight: ' + weight.to_s + '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  if quiz_question_choices&lt;br /&gt;
    quiz_question_choices.each do |choices|&lt;br /&gt;
      @html += if choices.iscorrect?&lt;br /&gt;
                '  - &amp;lt;b&amp;gt;' + choices.txt + '&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; '&lt;br /&gt;
              else&lt;br /&gt;
                '  - ' + choices.txt + '&amp;lt;br /&amp;gt; '&lt;br /&gt;
              end&lt;br /&gt;
    end&lt;br /&gt;
    @html += '&amp;lt;br /&amp;gt;'&lt;br /&gt;
  end&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end&amp;lt;/pre&amp;gt; || &amp;lt;pre&amp;gt;def view_question_text&lt;br /&gt;
  @html = &amp;quot;&amp;lt;b&amp;gt;#{txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Type: #{type} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; &amp;quot;Question Weight:#{weight.to_s} &amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  @html &amp;lt;&amp;lt; create_choices if quiz_question_choices.present?&lt;br /&gt;
  @html.html_safe&lt;br /&gt;
end &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_choices&lt;br /&gt;
  choices_html = &amp;quot;&amp;quot;&lt;br /&gt;
  quiz_question_choices.each do |choice|&lt;br /&gt;
    choices_html &amp;lt;&amp;lt; choice_html(choice)&lt;br /&gt;
  end&lt;br /&gt;
  choices_html &amp;lt;&amp;lt; &amp;quot;&amp;lt;br /&amp;gt;&amp;quot;&lt;br /&gt;
  choices_html&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def choice_html(choice)&lt;br /&gt;
  if choice.iscorrect?&lt;br /&gt;
    &amp;quot;  - &amp;lt;b&amp;gt;#{choice.txt}&amp;lt;/b&amp;gt;&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
    &amp;quot;  - #{choice.txt}&amp;lt;br /&amp;gt; &amp;quot;&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def all_choices_have_text?(choice_info)&lt;br /&gt;
  choice_info.all? { |_idx, value| value[:txt].present? }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
==== changes to testing hard coded html -&amp;gt; Nokogiri ====&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152346</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152346"/>
		<updated>2023-12-04T20:34:53Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Final Phase Changes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
=== Refactoring QuizQuestion and its child classes === &lt;br /&gt;
1. Extract Method &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
We applied the extract method to make the code more readable. &lt;br /&gt;
For example, in the &amp;lt;code&amp;gt; edit &amp;lt;/code&amp;gt; method in MultipleChoiceRadio, we created new methods and copied the relevant code fragments from &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; into the new methods. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
  @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
  @html = create_html_content&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Private methods:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def create_html_content&lt;br /&gt;
    html_content = &amp;quot;&amp;quot;&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_textarea_row&lt;br /&gt;
    html_content &amp;lt;&amp;lt; create_weight_input_row&lt;br /&gt;
    html_content&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
def create_textarea_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;textarea cols='100' name='question[#{id}][txt]' id='question_#{id}_txt'&amp;gt;#{txt}&amp;lt;/textarea&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def create_weight_input_row&lt;br /&gt;
  &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;Question Weight: &amp;lt;input type='number' name='question_weights[#{id}][txt]' id='question_wt_#{id}_txt' value='#{weight}' min='0' /&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Replacing &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt;&lt;br /&gt;
In Ruby, &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; can be used a string concatenation operator. We replaced all instances of using &amp;lt;code&amp;gt;+=&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;&amp;lt;&amp;lt;&amp;lt;/code&amp;gt; because we are modifying an existing object &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt; rather than creating a new object.&lt;br /&gt;
==== changes to testing hard coded html -&amp;gt; Nokogiri ====&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152341</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=152341"/>
		<updated>2023-12-04T20:14:29Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Final Phase Planning ===&lt;br /&gt;
* Further refactor quiz_question.rb and subclasses&lt;br /&gt;
* Currently, quiz_question.rb is a subclass of question.rb, however it does not follow the Liskov Substitution Principle because the method isvalid is not present in the superclass. By refactoring isvalid into the superclass, the entire Question hierarchy can be made more maintainable.&lt;br /&gt;
* Most methods of quiz_question.rb contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We plan to refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
&lt;br /&gt;
=== Further Refactor &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and subclasses ===&lt;br /&gt;
* Currently, &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; is a subclass of &amp;lt;code&amp;gt;question.rb&amp;lt;/code&amp;gt;, however it does not follow the Liskov Substitution Principle because the method &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; is not present in the superclass. By refactoring &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt; into the superclass, the entire &amp;lt;code&amp;gt;Question&amp;lt;/code&amp;gt; hierarchy can be made more maintainable.&lt;br /&gt;
&lt;br /&gt;
* Most methods of &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; contain hard-coded HTML, which makes the code inflexible and prone to breaking, and also violates SOP. We should refactor the HTML building logic out of the methods to improve readability and maintainability. This would also make testing easier.&lt;br /&gt;
&lt;br /&gt;
* The &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; method in &amp;lt;code&amp;gt;multiple_choice_checkbox.rb&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;multiple_choice_radio.rb&amp;lt;/code&amp;gt; uses the following code to generate the options: &amp;lt;code&amp;gt;[0, 1, 2, 3].each do |I|&amp;lt;/code&amp;gt;. This limits the number options to exactly 4. This should be refactored to allow an arbitrary number of choices in a range.&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
* Most existing Rspec tests for &amp;lt;code&amp;gt;quiz_question.rb&amp;lt;/code&amp;gt; and child classes test for exact strings that match the HTML. These tests will break if anything about the classes are changed, therefore they are not robust tests. The tests should be refactored to test the logic of these methods rather than their exact outputs.&lt;br /&gt;
&lt;br /&gt;
* In general, create additional tests after refactoring to verify that the refactored code work as intended. This includes functional testing to incorporate any additional helper classes created during the refactoring.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023&amp;diff=152074</id>
		<title>CSC/ECE 517 Fall 2023</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023&amp;diff=152074"/>
		<updated>2023-12-03T21:46:06Z</updated>

		<summary type="html">&lt;p&gt;Oysin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[CSC/ECE 517 Fall 2023 - E2350. Allow reviewers to bid on what to review]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2351. Finish mentor management for assignments without topics]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2352. Fix &amp;quot;Back&amp;quot; link on “New Late Policy” page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2353. Further refactoring and improvement of review mapping helper]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2355. Improving Search Facility In Expertiza]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2356. Refactor review_mapping_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2356. Refactor review_mapping_controller.rb (Phase 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2357. Refactor sign_up_sheet_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2358. Refactor student_quizzes_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2359. Refactor user_controller.rb, user.rb, and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2360. View for Results of Bidding]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2360. View for Results of Bidding (Phase2)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2361. Create a page to create and update a Questionnaire in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2362. Create a page to edit an Assignment's due date in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2363. Create a UI for Assignment Edit page &amp;quot;Etc&amp;quot; tab in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2364. Create a UI for Course's &amp;amp; Assignment's &amp;quot;Add Participants&amp;quot; page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2365. Create a user interface for Questionnaire in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2387. Reimplement Teams backend (Phase 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2367. Reimplement participants_controller.rb, participants.rb and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2368. Reimplement of due_date.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2369. Reimplement duties controller.rb and badges controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2371. Reimplement quiz_questionnaires_controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child_classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2373. Reimplementation of teams controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2373. Reimplement teams_controllers.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2374. Reimplement the Question hierarchy]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2375. Reimplement Waitlists]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2376. Reimplement student_quizzes_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2379. Reimplement authorization_helper.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2380. Reimplement frontend for Courses]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2381. Reimplement frontend for Assignments]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2383. Grading Audit Trail]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2384. Reimplement user_controller.rb, user.rb and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2385. Create a Courses User interface in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2386. Reimplement teams_users backend]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate_controller.rb)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-1 Adding Snapshot Controller/API and CRDs]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-2 Observability and Debuggability]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-3 Usability and Security]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-4 Extend NDB Operator capabilities to support Postgres HA]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - G2350. Add GitLab support for using GraphQL to query user metrics 1]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - G2352. Add GitLab support for using GraphQL to query repository information]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2375. Refactor classes relating to signing up for topics]]&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023&amp;diff=152073</id>
		<title>CSC/ECE 517 Fall 2023</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023&amp;diff=152073"/>
		<updated>2023-12-03T21:45:39Z</updated>

		<summary type="html">&lt;p&gt;Oysin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[CSC/ECE 517 Fall 2023 - E2350. Allow reviewers to bid on what to review]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2351. Finish mentor management for assignments without topics]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2352. Fix &amp;quot;Back&amp;quot; link on “New Late Policy” page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2353. Further refactoring and improvement of review mapping helper]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2355. Improving Search Facility In Expertiza]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2356. Refactor review_mapping_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2356. Refactor review_mapping_controller.rb (Phase 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2357. Refactor sign_up_sheet_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2358. Refactor student_quizzes_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2359. Refactor user_controller.rb, user.rb, and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2360. View for Results of Bidding]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2360. View for Results of Bidding (Phase2)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2361. Create a page to create and update a Questionnaire in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2362. Create a page to edit an Assignment's due date in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2363. Create a UI for Assignment Edit page &amp;quot;Etc&amp;quot; tab in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2364. Create a UI for Course's &amp;amp; Assignment's &amp;quot;Add Participants&amp;quot; page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2365. Create a user interface for Questionnaire in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2387. Reimplement Teams backend (Phase 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2366. Reimplement assignment model and assignment controller (Phase 2)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2367. Reimplement participants_controller.rb, participants.rb and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2368. Reimplement of due_date.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2369. Reimplement duties controller.rb and badges controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2370. Reimplement join team requests controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2371. Reimplement quiz_questionnaires_controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2372. Reimplement_QuizQuestion_and_its_child_classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2373. Reimplementation of teams controller]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2373. Reimplement teams_controllers.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2374. Reimplement the Question hierarchy]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2375. Reimplement Waitlists]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2376. Reimplement student_quizzes_controller.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2379. Reimplement authorization_helper.rb]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2380. Reimplement frontend for Courses]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2381. Reimplement frontend for Assignments]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2382. Optimizing the LatePoliciesController]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2383. Grading Audit Trail]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2384. Reimplement user_controller.rb, user.rb and its child classes]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2385. Create a Courses User interface in ReactJS]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2386. Reimplement teams_users backend]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2377. Reimplement impersonating users (functionality within impersonate_controller.rb)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-1 Adding Snapshot Controller/API and CRDs]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-2 Observability and Debuggability]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-3 Usability and Security]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - NTX-4 Extend NDB Operator capabilities to support Postgres HA]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - G2350. Add GitLab support for using GraphQL to query user metrics 1]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - G2352. Add GitLab support for using GraphQL to query repository information]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2023 - E2375. Refactor classes relating to signing up for topics]]&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151293</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151293"/>
		<updated>2023-11-14T16:00:18Z</updated>

		<summary type="html">&lt;p&gt;Oysin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Final Phase Changes ==&lt;br /&gt;
&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To be completed.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151234</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151234"/>
		<updated>2023-11-07T02:59:22Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use &amp;lt;code&amp;gt;@html&amp;lt;/code&amp;gt; (an instance variable) instead of &amp;lt;code&amp;gt;html.&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To be completed.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151104</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151104"/>
		<updated>2023-11-03T19:10:31Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Testing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
To be completed.&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151103</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151103"/>
		<updated>2023-11-03T19:09:47Z</updated>

		<summary type="html">&lt;p&gt;Oysin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151102</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151102"/>
		<updated>2023-11-03T19:05:24Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid(choice_info)&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    @quiz_question_choices = QuizQuestionChoice.where(question_id: id)&lt;br /&gt;
&lt;br /&gt;
    @html = '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;textarea cols=&amp;quot;100&amp;quot; name=&amp;quot;question[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_' + id.to_s + '_txt&amp;quot;&amp;gt;' + txt + '&amp;lt;/textarea&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
    @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
    @html += 'Question Weight: '&lt;br /&gt;
    @html += '&amp;lt;input type=&amp;quot;number&amp;quot; name=&amp;quot;question_weights[' + id.to_s + '][txt]&amp;quot; '&lt;br /&gt;
    @html += 'id=&amp;quot;question_wt_' + id.to_s + '_txt&amp;quot; '&lt;br /&gt;
    @html += 'value=&amp;quot;' + weight.to_s + '&amp;quot; min=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
    @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in MultipleChoiceCheckbox&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def edit&lt;br /&gt;
    super&lt;br /&gt;
    # for i in 0..3&lt;br /&gt;
    [0, 1, 2, 3].each do |i|&lt;br /&gt;
      @html += '&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;0&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;checkbox&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][iscorrect]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_iscorrect&amp;quot; value=&amp;quot;1&amp;quot; '&lt;br /&gt;
      @html += 'checked=&amp;quot;checked&amp;quot; ' if @quiz_question_choices[i].iscorrect&lt;br /&gt;
      @html += '/&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;quiz_question_choices[' + id.to_s + '][MultipleChoiceCheckbox][' + (i + 1).to_s + '][txt]&amp;quot; '&lt;br /&gt;
      @html += 'id=&amp;quot;quiz_question_choices_' + id.to_s + '_MultipleChoiceCheckbox_' + (i + 1).to_s + '_txt&amp;quot; '&lt;br /&gt;
      @html += 'value=&amp;quot;' + @quiz_question_choices[i].txt + '&amp;quot; size=&amp;quot;40&amp;quot; /&amp;gt;'&lt;br /&gt;
&lt;br /&gt;
      @html += '&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;'&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    @html.html_safe&lt;br /&gt;
    # safe_join(@html)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151101</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151101"/>
		<updated>2023-11-03T19:02:48Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; in QuizQuestion.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151100</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151100"/>
		<updated>2023-11-03T18:55:26Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We implemented &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151099</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151099"/>
		<updated>2023-11-03T18:55:04Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
* We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
* We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151098</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151098"/>
		<updated>2023-11-03T18:54:48Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151097</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151097"/>
		<updated>2023-11-03T18:47:30Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151096</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151096"/>
		<updated>2023-11-03T18:35:09Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end &lt;br /&gt;
&lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151095</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151095"/>
		<updated>2023-11-03T18:34:55Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
'''&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end &lt;br /&gt;
'''&lt;br /&gt;
&lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151094</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151094"/>
		<updated>2023-11-03T18:28:08Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end &lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151093</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151093"/>
		<updated>2023-11-03T18:25:49Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
&amp;lt;code&amp;gt;def isvalid(choice_info)&lt;br /&gt;
  @valid = 'valid'&lt;br /&gt;
  @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
  @valid&lt;br /&gt;
end &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151092</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151092"/>
		<updated>2023-11-03T18:25:31Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
&amp;lt;code&amp;gt;def isvalid(choice_info)&lt;br /&gt;
    @valid = 'valid'&lt;br /&gt;
    @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
    @valid&lt;br /&gt;
end &amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151091</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151091"/>
		<updated>2023-11-03T18:25:12Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
def isvalid(choice_info)&lt;br /&gt;
    @valid = 'valid'&lt;br /&gt;
    @valid = 'Please make sure all questions have text' if txt == ''&lt;br /&gt;
    @valid&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151090</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151090"/>
		<updated>2023-11-03T18:23:45Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt;isvalid()&amp;lt;/code&amp;gt; to QuizQuestion. &lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151089</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151089"/>
		<updated>2023-11-03T18:23:25Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
# We added &amp;lt;code&amp;gt; isvalid() &amp;lt;/code&amp;gt; to QuizQuestion. &lt;br /&gt;
# We factored out duplicate code in &amp;lt;code&amp;gt;edit()&amp;lt;/code&amp;gt; from the subclasses and placed it into the superclass QuizQuestion. Now &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; in the subclasses inherit partially from QuizQuestion.&lt;br /&gt;
# We reimplemented QuizQuestion class and child classes methods to use @html (an instance variable) instead of html.&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151088</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151088"/>
		<updated>2023-11-03T18:16:10Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Objectives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;:  What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
Our goals are&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
adds isvalid() to QuizQuestion&lt;br /&gt;
implements edit() within QuizQuestion&lt;br /&gt;
Reimplements QuizQuestion class and child classes methods to use @html instead of html&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151087</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151087"/>
		<updated>2023-11-03T18:15:39Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Objectives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
&lt;br /&gt;
There are four methods in QuizQuestion super class. edit, view_question_text, view_completed_question, and complete. These 4 (model) methods will return different html strings depends on the question type.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt; What to display` - if an instructor (etc.) is creating or editing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt; - What to display if an instructor (etc.) is viewing a questionnaire (questionnaires_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt; What to display - if a student is filling out a questionnaire (response_controller.rb)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt; - What to display if a student is viewing a filled-out questionnaire (response_controller.rb)&lt;br /&gt;
&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
adds isvalid() to QuizQuestion&lt;br /&gt;
implements edit() within QuizQuestion&lt;br /&gt;
Reimplements QuizQuestion class and child classes methods to use @html instead of html&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151086</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151086"/>
		<updated>2023-11-03T18:14:57Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Our Solution */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
adds isvalid() to QuizQuestion&lt;br /&gt;
implements edit() within QuizQuestion&lt;br /&gt;
Reimplements QuizQuestion class and child classes methods to use @html instead of html&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151085</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151085"/>
		<updated>2023-11-03T17:20:31Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Overview of the Classes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== true_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151084</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151084"/>
		<updated>2023-11-03T17:19:19Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* TrueFalse */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== ture_false.rb ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151083</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151083"/>
		<updated>2023-11-03T17:19:04Z</updated>

		<summary type="html">&lt;p&gt;Oysin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== TrueFalse ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Our Solution ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151082</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151082"/>
		<updated>2023-11-03T17:15:01Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* UML Diagram */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== TrueFalse ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[[File:E2372. Reimplement QuizQuestion and its child classes.png]]&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:E2372._Reimplement_QuizQuestion_and_its_child_classes.png&amp;diff=151081</id>
		<title>File:E2372. Reimplement QuizQuestion and its child classes.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:E2372._Reimplement_QuizQuestion_and_its_child_classes.png&amp;diff=151081"/>
		<updated>2023-11-03T17:14:30Z</updated>

		<summary type="html">&lt;p&gt;Oysin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151080</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151080"/>
		<updated>2023-11-03T17:13:57Z</updated>

		<summary type="html">&lt;p&gt;Oysin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== TrueFalse ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== UML Diagram ==&lt;br /&gt;
[&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151079</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151079"/>
		<updated>2023-11-03T17:12:06Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* Overview of the Classes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* &amp;lt;code&amp;gt;complete method&amp;lt;/code&amp;gt;: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== TrueFalse ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: render the true/false question for the user to answer&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: displays the correct answer and the user's answer&lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151078</id>
		<title>CSC/ECE 517 Fall 2023 - E2372. Reimplement QuizQuestion and its child classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2023_-_E2372._Reimplement_QuizQuestion_and_its_child_classes&amp;diff=151078"/>
		<updated>2023-11-03T17:11:27Z</updated>

		<summary type="html">&lt;p&gt;Oysin: /* quiz_question.rb */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
== Objectives ==&lt;br /&gt;
# Make a complete UML diagram for these classes with their attributes, methods, and class methods.&lt;br /&gt;
# Check all implementations of instance methods, extract duplicated codes, and put them into the highest-level class.&lt;br /&gt;
# Thoroughly test the QuizQuestion class&lt;br /&gt;
&lt;br /&gt;
== Overview of the Classes == &lt;br /&gt;
=== quiz_question.rb ===&lt;br /&gt;
QuizQuestion is a base class used to represent a question in a quiz. It inherits from the Question class. This class is associated with QuizQuestionChoice objects through a has_many relationship, indicating that a QuizQuestion can have multiple choices. It handles the creation of HTML for different views related to a question, such as editing, completing, and viewing the question text.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;edit&amp;lt;/code&amp;gt;: to generate the HTML form for editing a question, &lt;br /&gt;
* &amp;lt;code&amp;gt;complete&amp;lt;/code&amp;gt;: used for completing the question in the quiz&lt;br /&gt;
* &amp;lt;code&amp;gt;view_question_text&amp;lt;/code&amp;gt;: to display the question and its choices)&lt;br /&gt;
* &amp;lt;code&amp;gt;view_completed_question&amp;lt;/code&amp;gt;: abstract method used after quiz has been submitted, and &lt;br /&gt;
* &amp;lt;code&amp;gt;isvalid&amp;lt;/code&amp;gt;: to validate the question, especially ensuring it has text&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_radio.rb ===&lt;br /&gt;
This class extends QuizQuestion and represents a multiple-choice question where the participant can select only one answer from a set of radio buttons.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* edit: overridden to add HTML for a set of radio buttons that allows the user to select one choice as the correct answer; also includes text inputs for the choices' text&lt;br /&gt;
* complete method: renders HTML for the user to complete this type of question in a quiz interface&lt;br /&gt;
* view_completed_question: displays the correct answer, the user's answer, and visual feedback on whether the user's answer was correct&lt;br /&gt;
* isvalid: extended to ensure that not only does each choice have text, but also that exactly one correct answer is selected&lt;br /&gt;
&lt;br /&gt;
=== multiple_choice_checkbox.rb ===&lt;br /&gt;
The MultipleChoiceCheckbox class is a subclass of QuizQuestion and represents a multiple-choice question where the participant can select multiple answers through checkboxes.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
&lt;br /&gt;
* edit: add HTML input elements for checkboxes, allowing multiple correct answers to be selected, along with text inputs for entering the choices.&lt;br /&gt;
* complete: allows users to complete the question, displaying checkboxes for them to select their answers&lt;br /&gt;
* view_completed_question: shows correct answers and whether the user's selections were correct&lt;br /&gt;
* isvalid: validates the question, ensures there are multiple correct answers if it's a checkbox question.&lt;br /&gt;
&lt;br /&gt;
=== TrueFalse ===&lt;br /&gt;
This class also extends QuizQuestion and is specialized for true/false questions.&lt;br /&gt;
&lt;br /&gt;
Methods:&lt;br /&gt;
* edit: includes HTML radio buttons specifically for 'True' and 'False' options&lt;br /&gt;
* complete: render the true/false question for the user to answer&lt;br /&gt;
* view_completed_question: displays the correct answer and the user's answer&lt;br /&gt;
* isvalid: checks to ensure that the question has text and that a correct answer is designated&lt;br /&gt;
&lt;br /&gt;
== Testing ==&lt;br /&gt;
&lt;br /&gt;
== Relevant Links ==&lt;br /&gt;
&lt;br /&gt;
'''Github repository: ''' https://github.com/opheliasin/expertiza&lt;br /&gt;
&lt;br /&gt;
'''Pull request: '''https://github.com/expertiza/expertiza/pull/2682&lt;br /&gt;
&lt;br /&gt;
== Team == &lt;br /&gt;
'''Mentor'''&lt;br /&gt;
&lt;br /&gt;
Aditi Vakeel &lt;br /&gt;
&lt;br /&gt;
'''Members'''&lt;br /&gt;
&lt;br /&gt;
Nathan Sudduth (ncsuddut@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Ophelia Sin (oysin@ncsu.edu)&lt;br /&gt;
&lt;br /&gt;
Yi Chen (ychen282@ncsu.edu)&lt;/div&gt;</summary>
		<author><name>Oysin</name></author>
	</entry>
</feed>