CSC/ECE 517 Fall 2017/E1794. Student-generated questions added to rubric
Introduction
Instructors make up rubrics in Expertiza. They can ask about anything that is relevant to all the projects that will be submitted. But sometimes students want specific advice on aspects of their work that may be different from the work or topics that other students are working on. It would be more convinient if students can add their own questionnaire to ask feedback for some specific functionalities regarding their project.
Changes implemented
Note: These changes are covered in Use Case section.
Design Principles to be Followed
1. MVC - The project is implemented in Ruby on Rails that uses MVC architecture. It separates an application’s data model, user interface, and control logic into three distinct components (model, view and controller, respectively).
2. Dry Principle - We are trying to reuse the existing functionalities in Expertiza, thus avoiding code duplication. Whenever possible, code modification based on the existing classes, controllers, or tables will be done instead of creating the new one.
3. Polymorphism
4. Inheritance
Use Case
Here SRQ is used for newly added field supplementaryReviewQuestions in the Teams table and it is initially set as null for all the table entries.Once a student adds a specific Questionnaire to his project this field stores the id of that Questionnaire which is stored in the Questionnaires table.
To provide the view for the scores of a team we will add one more partition containing the scores for the supplementary questionnaire and implement the already build logic to get and display the scores.
Files edited:
grades_controller.rb
response_controller.rb
submitted_content_controller.rb
response.rb
team.rb
grades/view_team.html.erb
response/response.html.erb
submitted_content/_main.html.erb
routes.rb
migration script
view_team_in_grades.js
Implementation
1. Created a migration script to add a new column 'supplementary_rubric' to the Teams table
2. To add supplementary rubric: In submitted_content_controller.rb: created a new function 'manage_supplementary_rubric'
def manage_supplementary_rubric @participant = AssignmentParticipant.find(params[:id]) @team = Team.find(@participant.team.id) if @team.supplementary_rubric.nil? then @questionnaire = Questionnaire.new @questionnaire.private = false @questionnaire.name = "SR_" + @team.id.to_s @questionnaire.instructor_id = @team.id @questionnaire.min_question_score = 0 @questionnaire.max_question_score = 5 @questionnaire.type = "ReviewQuestionnaire" @questionnaire.display_type = "Review" @questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL begin @questionnaire.save @team.supplementary_rubric = @questionnaire.id @team.save flash[:success] = 'You have successfully created a questionnaire!' rescue flash[:error] = $ERROR_INFO end else @questionnaire = Questionnaire.find(@team.supplementary_rubric) end redirect_to controller: 'questionnaires', action: 'edit', id: @questionnaire.id end
In the view, submitted_content/_mail.html.erb: Created a button 'Manage Supplementary rubric' to be shown in 'your work' tab
<% if stage != "Finished" %> <%= button_to :action => "manage_supplementary_rubric", :id => participant.id do %> Manage Supplementary Rubric <% end %> <% end %>
After this, the same functionality of adding a rubric and questions is used as before.
3. To display the supplementary rubric questions: In response_controller.rb: Changes in create, set_content, set_questionnaire_for_new_response, set_questionnaire
# For Supp Questions unless @supp_questionnaire.nil? questions_supp = sort_questions(@supp_questionnaire.questions) questions = questions+questions_supp end ###
in set content
# For supp Questionnaire unless @supp_questionnaire.nil? @questions_supp = sort_questions(@supp_questionnaire.questions) end ###
in set_questionnaire_for_new_response
# For supp Questionnaire @supp_questionnaire_id = Team.supplementary_rubric_by_team_id(@contributor.id) unless @supp_questionnaire_id.nil? @supp_questionnaire = Questionnaire.find(@supp_questionnaire_id) end ###
in set_questionnaire
answer_supp = @response.scores.last @supp_questionnaire = Questionnaire.find(@supp_questionnaire_id) @supp_questionnaire = @response.questionnaire_by_answer(answer_supp)
In View, response/response.html.erb: added code to display supplementary questions.
<% unless @questions_supp.nil?%> <%@questions_supp.each do |question| %> <% answer = Answer.where(question_id: question.id, response_id: @response.id).first if !@response.nil?%> <% if question.instance_of? Criterion%> <%= question.complete(i, answer, @questionnaire.min_question_score, @questionnaire.max_question_score, @dropdown_or_scale) %> <% elsif question.instance_of? Scale %> <%= question.complete(i, answer, @questionnaire.min_question_score, @questionnaire.max_question_score) %> <% elsif question.instance_of? UploadFile %> <% else %> <%= question.complete(i, answer) %> <% end %> <% i += 1%> <% end %> <% end %>
4. To edit a review if saved: In response_controller.rb: Changes in edit, update
# For Supp Questions questions_supp = sort_questions(@supp_questionnaire.questions) all_questions = questions+questions_supp
5. For the reviewer and the reviewee to view the completed review: Model: response.rb: Created new function, display_html_helper.
def display_html_helper(questions, answers, questionnaire_max) count = 0 code = questions.each do |question| count += 1 if !question.is_a? QuestionnaireHeader and question.break_before == true answer = answers.find {|a| a.question_id == question.id } row_class = count.even? ? "info" : "warning" row_class = "" if question.is_a? QuestionnaireHeadercode += ''
if !answer.nil? or question.is_a? QuestionnaireHeader code += if question.instance_of? Criterion or question.instance_of? Scale question.view_completed_question(count, answer, questionnaire_max) else question.view_completed_question(count, answer) end endcode += '' end return code end and made changes in display_as_html function. # For supp_questionnaire response_map = self.map reviewee_id = response_map.reviewee_id supp_questionnaire_id = Team.supplementary_rubric_by_team_id(reviewee_id) unless supp_questionnaire_id.nil? supp_questionnaire = Questionnaire.find(supp_questionnaire_id) supp_questions = supp_questionnaire.questions.sort {|a, b| a.seq <=> b.seq } end 6. For the reviewee to see the review in heat chart: grades_controller.rb: view_team function, added code for supplementary questions, # For Supp questionnaire supp_questionnaire_id = Team.supplementary_rubric_by_team_id(@team_id) if not supp_questionnaire_id.nil? supp = VmQuestionResponse.new(questionnaire, @round, @assignment.rounds_of_reviews) supp_questionnaire = Questionnaire.find(supp_questionnaire_id) supp_questions = supp_questionnaire.questions supp.add_questions(supp_questions) supp.add_team_members(@team) supp.add_reviews(@participant, @team, @assignment.varying_rubrics_by_round?) supp.get_number_of_comments_greater_than_10_words @supplist << supp else @supplist << nil end ### created separate VmQuestionResponse for supplentary questions.
Test Plan
Because of the addition of supplementary questions, some of the original spec tests failed. So we started by fixing it.
1. Due to addition of one more column in the teams table, we had to fix spec/models/assignment_spec.rb, where we added another field called supplementary_rubric in the final expected result
describe '#scores' do
context 'when assignment is varying rubric by round assignment' do it 'calculates scores in each round of each team in current assignment' do allow(participant).to receive(:scores).with(review1: [question]).and_return(98) allow(assignment).to receive(:varying_rubrics_by_round?).and_return(true) allow(assignment).to receive(:num_review_rounds).and_return(1) allow(ReviewResponseMap).to receive(:get_responses_for_team_round).with(team, 1).and_return([response]) allow(Answer).to receive(:compute_scores).with([response], [question]).and_return(max: 95, min: 88, avg: 90) expect(assignment.scores(review1: [question]).inspect).to eq("{:participants=>{:\"1\"=>98}, :teams=>{:\"0\"=>{:team=>#<AssignmentTeam id: 1, "\ "name: \"no team\", parent_id: 1, type: \"AssignmentTeam\", comments_for_advertisement: nil, advertise_for_partner: nil, "\ "submitted_hyperlinks: \"---\\n- https://www.expertiza.ncsu.edu\", directory_num: 0, grade_for_submission: nil, "\ "comment_for_submission: nil, supplementary_rubric: nil>, :scores=>{:max=>95, :min=>88, :avg=>90.0}}}}") end end
context 'when assignment is not varying rubric by round assignment' do it 'calculates scores of each team in current assignment' do allow(participant).to receive(:scores).with(review: [question]).and_return(98) allow(assignment).to receive(:varying_rubrics_by_round?).and_return(false) allow(ReviewResponseMap).to receive(:get_assessments_for).with(team).and_return([response]) allow(Answer).to receive(:compute_scores).with([response], [question]).and_return(max: 95, min: 88, avg: 90) expect(assignment.scores(review: [question]).inspect).to eq("{:participants=>{:\"1\"=>98}, :teams=>{:\"0\"=>{:team=>#<AssignmentTeam id: 1, "\ "name: \"no team\", parent_id: 1, type: \"AssignmentTeam\", comments_for_advertisement: nil, advertise_for_partner: nil, "\ "submitted_hyperlinks: \"---\\n- https://www.expertiza.ncsu.edu\", directory_num: 0, grade_for_submission: nil, "\ "comment_for_submission: nil, supplementary_rubric: nil>, :scores=>{:max=>95, :min=>88, :avg=>90}}}}") end end end
2. We also changed spec/controllers/response_controller_spec.rb in which due to addition of supplementary questionnaire, we had now 2 answers in the expected results.
expect(controller.instance_variable_get(:@review_scores)).to eq([answer, answer])
We added a couple of rspec tests for the code to check the sanity of changes in supplementary questionnaire:
1. To check if "Manage Supplementary Rubric" is being displayed in the Your work page of a student participating in an assignment.
2. To check if clicking on "Manage Supplementary Rubric button" creates a questionnaire id in Supplementary rubric column of Teams Table.
3. To check if a reviewer creates a Rubric, the assigned student is able to see the Supplementary Review Questionnaire whenever he/she logs in and tries to review it.
To make the code DRY we created a new TopicHelper.rb to make signup to a topic and submit content reusable.
We created a new spec file supplementary_rubric_spec.rb for testing the added functionality.
include TopicHelper describe "supplementary rubric testing" do before(:each) do # create assignment and topic create(:assignment, name: "TestAssignment", directory_path: "TestAssignment") create_list(:participant, 3) create(:assignment_team) create(:team_user, user: User.where(role_id: 2).first, team: AssignmentTeam.first) create(:topic, topic_name: "TestTopic") create(:deadline_type, name: "submission") create(:deadline_type, name: "review") create(:deadline_type, name: "metareview") create(:deadline_type, name: "drop_topic") create(:deadline_type, name: "signup") create(:deadline_type, name: "team_formation") create(:deadline_right) create(:deadline_right, name: 'Late') create(:deadline_right, name: 'OK') create(:assignment_questionnaire) create(:questionnaire) create(:question) create(:assignment_due_date, deadline_type: DeadlineType.where(name: "submission").first, due_at: DateTime.now.in_time_zone + 1.day) end
it "has manage rubric button to add/edit supplementary questionnaire" do signup_topic expect(page).to have_content "Manage Supplementary Rubric" end
it "add supplementary questionnaire to teams model" do signup_topic click_button "Manage Supplementary Rubric" assert !Team.supplementary_rubric_by_team_id(2).nil? end
it "should display Supplementary Questionnaire to assigned student" do submit_to_topic click_button "Manage Supplementary Rubric" click_button "Add" click_button "Save review questionnaire" user = User.find_by(name: "student2066") stub_current_user(user, user.role.name, user.role) visit '/student_task/list' click_link "TestAssignment" click_link "Others' work" find(:css, "#i_dont_care").set(true) click_button "Request a new submission to review" click_link "Begin" expect(page).to have_content "Supplementary Reviewee Generated Questions" end end